英文:
How to properly infer nested and complex types in Typescript?
问题
我认为有时候 TypeScript 在处理复杂和嵌套类型时无法正确地进行类型推断。
我需要知道这是否是一个 bug,还是我做错了。如果我做错了,那么实现嵌套和复杂类型的推断的最佳方法是什么?
到目前为止,我提出了以下代码:
// Storable 类型是具有可选 key 属性的对象
type Storable<O, Key extends string> = O & { [key in Key]?: string };
// Stored 类型是具有必需 key 属性的对象
type Stored<S> = S extends Storable<infer O, infer Key extends string> ? O & { [key in Key]: string } : never
// MyObject 是一个标准对象
type MyObject = { prop1: boolean; prop2: number; };
// MyStorableObject 是一个 Storable MyObject
type MyStorableObject = Storable<MyObject, "id">;
// 将一个 Storable 对象转换为 Stored 对象
function store<T, B extends string>(object: Storable<T, B>, key: B): Stored<T> {
return { ...object, [key]: 'generatedId' } as unknown as Stored<T>;
}
当我调用 store 函数时,我期望 stored 不是 never
类型:
const storableObject: MyStorableObject = { prop1: true, prop2: 0 };
const stored = store(storableObject, 'id');
奇怪的是,有时它工作正常,有时它不工作。例如,使用这个 MyObject 类型:
type MyObject = { prop1: string };
存储的对象类型是我所期望的:
const stored: MyObject & {
id?: string | undefined;
} & {
id: string;
prop1: string;
}
英文:
I think sometimes Typescript does not infer properly when it comes to complex and nested types.
I need to know if it's a bug or if I'm doing wrong. And if I'm doing wrong, what is the best way to achieve inference of nested and complex types ?
I came up with this code so far:
// Storable type is the Object with an optional key prop
type Storable<O, Key extends string> = O & { [key in Key]?: string };
// Stored type is the Object with a required key prop
type Stored<S> = S extends Storable<infer O, infer Key extends string> ? O & { [key in Key]: string} : never
// MyObject is a standard object
type MyObject = { prop1: boolean; prop2: number; };
// MyStorableObject is a Storable MyObject
type MyStorableObject = Storable<MyObject, "id">;
// Transforms a Storable object to a Stored object
function store<T, B extends string>(object: Storable<T, B>, key: B): Stored<T> {
return { ...object, [key]: 'generatedId' } as unknown as Stored<T>;
}
When I call store function, I expect stored not to be never type :
const storableObject:MyStorableObject = { prop1: true, prop2: 0 };
const stored = store(storableObject, 'id');
What is weird is that sometimes, it works, sometimes it doesn't. For example, with this MyObject type :
type MyObject = { prop1: string };
The stored object type is what I expect:
const stored: MyObject & {
id?: string | undefined;
} & {
id: string;
prop1: string;
}
答案1
得分: 1
我认为问题出在你从 store
返回的部分。
Stored
接受一个泛型参数,它期望扩展自 Storable
,但在 store
中当你返回 Stored<T>
时,实际上你返回的是 Stored<MyObject>
,而 MyObject
并没有扩展自 Storable
,这就是为什么 stored
的类型是 never
的原因。
所以,你最简单的解决方案是将返回类型更改为 Stored<Storable<T, B>>
。
英文:
I think that the problem is what you are returning from store
.
Stored
takes a generic parameter that is expecting to extends Storable
, but when in store
you are returning Stored<T>
, you are actually returning Stored<MyObject>
, and MyObject
doesn't extends Storable
, that is why stored
is of type never
.
So your simplest solution is to change the return type to Stored<Storable<T, B>>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论