我正在编写类型检查构造函数。 我希望返回对象类型具有与参数值完全相同的字段值,但另一个字段取决于该值。
function testConstructor<T extends En>(
val: T
): {
field: T;
[x: string]: any;
} {
switch (val) {
case En.one:
return {
field: En.one,
anotherField: 1,
};
case En.two:
return {
field: En.two,
someAnotherField: 2,
};
default:
return {
field: val,
};
}
}
我收到一个错误:
TS2322: Type 'En.two' is not assignable to type 'T'. 'En.two' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'En'.
为什么我总是收到这个错误,我该如何解决? 为什么开关防护不起作用?
@Phu-Ngo 解决方案后的错误(此版本的代码更接近我的实际代码。)
enum Enum {
one = 'one',
two = 'two',
}
type Type1 = {
field: typeof Enum.one;
anotherField: number;
};
type Type2 = {
field: typeof Enum.two;
someAnotherField: number;
};
function testConstructor<T extends Enum>(
val: T
): {
field: T;
[x: string]: any;
} {
switch (val) {
case Enum.one:
let obj1: Type1 = {
field: val,
anotherField: 1,
};
return obj1;
case Enum.two:
let obj2: Type2 = {
field: val,
someAnotherField: 1,
}
return obj2;
}
throw Error(`unknown value ${val}`);
}
错误:
field: val
行:TS2322: Type 'T' is not assignable to type 'Enum.one'. Type 'Enum' is not assignable to type 'Enum.one'.
return obj1
行:TS2322: Type 'Type1' is not assignable to type '{ [x: string]: any; field: T; }'. Types of property 'field' are incompatible. Type 'Enum.one' is not assignable to type 'T'. 'Enum.one' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Enum'.
答案 0 :(得分:0)
不是用一个构造函数而是用 mapped 构造函数和 Extract 解决的。
enum Enum {
one = 'one',
two = 'two',
}
type Type1 = {
field: typeof Enum.one;
anotherField: number;
};
type Type2 = {
field: typeof Enum.two;
someAnotherField: number;
};
type TypeN = Type1 | Type2;
type ConstructorN<T> = () => Extract<
TypeN,
{
field: T;
}
>;
type Constructors = {
[T in Enum]: ConstructorN<T>;
};
let constructors: Constructors = {
[Enum.one]: () => {
let obj: Type1 = {
field: Enum.one,
anotherField: 1,
};
return obj;
},
[Enum.two]: () => {
let obj: Type2 = {
field: Enum.two,
someAnotherField: 2,
};
return obj;
},
};
console.log(constructors[Enum.one]())
console.log(constructors[Enum.two]())