Typescript 如何使用条件类型在函数体中缩小类型范围
我定义了一个条件类型,以便根据第一个参数的类型约束类构造函数的第二个参数 类型检查器正确地标识了调用构造函数时允许的内容。但是,在我的构造函数中,我无法让编译器推断类型Typescript 如何使用条件类型在函数体中缩小类型范围,typescript,Typescript,我定义了一个条件类型,以便根据第一个参数的类型约束类构造函数的第二个参数 类型检查器正确地标识了调用构造函数时允许的内容。但是,在我的构造函数中,我无法让编译器推断类型 enum Type { A = 'A', B = 'B', } type TypeKeys<T extends Type> = T extends Type.A ? {a: number} : T extends Type.B ? {b: number} : never; class
enum Type {
A = 'A',
B = 'B',
}
type TypeKeys<T extends Type> =
T extends Type.A ? {a: number} :
T extends Type.B ? {b: number} : never;
class TestClass<T extends Type> {
constructor(type: T, data: TypeKeys<T>) {
if(type === Type.A) {
data.a // Property 'a' does not exist on type 'TypeKeys<T>'.
}
}
}
new TestClass(Type.A, {a: 10})
//Argument of type '{ a: number; }' is not assignable to parameter of type '{ b: number; }'.
new TestClass(Type.B, {a: 10})
枚举类型{
A=‘A’,
B=‘B’,
}
打字键=
T扩展类型A?{a:number}:
T扩展了B型?{b:number}:从不;
类TestClass{
构造函数(类型:T,数据:类型键){
如果(类型===类型A){
data.a//类型“TypeKeys”上不存在属性“a”。
}
}
}
新的TestClass(Type.A,{A:10})
//类型为“{a:number;}”的参数不能分配给类型为“{b:number;}”的参数。
新的TestClass(Type.B,{a:10})
有没有一种方法可以利用构造函数主体内部的类型缩小功能?一种方法是使用。在两个接口上添加类型为类型的共享属性(kind
)。也就是说,TypeScript可以“区分”构造函数主体内部和外部的类型
枚举类型{
A=‘A’,
B=‘B’,
}
接口A{
种类:A型;
a:数字;
}
接口B{
种类:B型;
b:数字;
}
类TestClass{
建造商(数据:A | B){
if(data.kind==Type.A){
数据a=5;
}否则{
data.a//类型“TypeKeys”上不存在属性“a”。
}
}
}
新的TestClass({kind:Type.A,A:10})
//类型为“{a:number;}”的参数不能分配给类型为“{b:number;}”的参数。
新的TestClass({kind:Type.B,a:10})
我猜编译器还不够聪明,无法隐式地判断代码是否安全。以下是我认为正在发生的事情:
当您创建类的新实例时,编译器会看到您的类型约束,并正确地防止您向其传递错误的数据。但是,在构造函数中,它似乎没有在两个不同的变量之间传播约束。我想可能是因为如果有多个变量控制数据的类型,它可能会变得非常复杂
Typescript确实有一种称为歧视联合(discriminated unions)的东西,它是为这样的情况而设计的,尽管从个人经验来看,我发现自动类型推断有缺陷,在某些情况下根本不起作用。我已经放弃了让它自动推断类型,所以我经常进行转换以使事情正常工作:
if (data.type === Type.A) {
const dataA = <A>data;
dataA.a;
}
if(data.type==type.A){
const dataA=数据;
dataA.a;
}
我在一些项目中使用了歧视性的联合,但我发现它们有缺陷。我经常必须明确地将其转换为任何类型。我从来没有遇到过歧视工会的问题。我对此很好奇。你有任何有问题的示例代码吗?我也没有遇到歧视工会的问题。我决定采用这种方法,但我在定义原始类型时内联了接口定义。谢谢当然,这是我在typescript回购协议上打开的一个旧版本。回过头来看,我的问题似乎与歧视联合有关,它与实现接口的类不按预期工作: