对于可能有Ids的事物,我有一个基本的接口:
interface Identifiable {
id?: number;
}我有一个泛型函数,可以将一个记录对象转换为一个id为的东西:
function fromRowToObj1<T extends Identifiable>(row: { id: number; }): Partial<T> {
return { id: row.id };
// Type '{ id: number; }' is not assignable to type 'Partial<T>'.
}我知道发生这种情况是因为有一些扩展Identifiable的T会使该返回语句非法。例如,类型{ id: undefined }或{ id: 1 }。因此我决定对返回类型进行一些调整,以强制使用数字id:
type Identified<T extends Identifiable> = {
[K in keyof T]?: K extends "id" ? number : T[K];
}
// Should give something like type C = { id?: number | undefined; ... }
function fromRowToObj2<T extends Identifiable>(row: { id: number; }): Identified<T> {
return { id: row.id };
// Type '{ id: number; }' is not assignable to type 'Identified<T>'.
}但是为什么呢?哪种可能的T (例如T extends Identifiable)使它不能将{ id: number }赋值给Identified<T>
如果无法调整Identified类型以使其正常工作,是否有其他方法可以键入转换函数以使用Identifiable的泛型子类型
发布于 2021-04-09 06:03:40
您所面临的问题已在here中得到了全面的描述。正如您所注意到的,T extends Identifiable的一些子类型使得返回值{ id: row.id }无效。例如,Identified<{id?: never}>永远不会对{ id: row.id }有效。Never仍然是id的有效类型,因为您已将Identified的所有键声明为可选。如果为T extends Identifiable,则Identified<T>实际上等于Partial<T>。Typescript正确地在这里抛出一个错误。但是,如果您设置了有效的默认值(playground),您仍然可以解决这个问题:
interface Identifiable {
id?: number;
}
// results in optional id
function fromRowToObj1<T extends Identifiable>(row: { id: number; }) {
const result: Partial<T> = {} // valid for all subtypes of Partial<T>
result.id = row.id
return result;
}
// results in non optional id
function fromRowToObj2<T extends Identifiable>(row: { id: number; } ) {
const partial: Partial<T> = {}; // valid for all subtypes of Partial<T>
const result = {
...partial,
id: row.id
};
return result;
}
interface TestObject {
id: number,
arg1: string;
arg2: boolean;
}
const result1 = fromRowToObj1<TestObject>({id: 5});
result1.id // optional
result1.arg1 = "test" // intellisense works
result1.arg2 = true; // intellisense works
const result2 = fromRowToObj2<TestObject>({id: 5});
result2.id // not optional
result2.arg1 = "test" // intellisense works
result2.arg2 = true; // intellisense workshttps://stackoverflow.com/questions/67011244
复制相似问题