Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 如何使用条件类型在函数体中缩小类型范围_Typescript - Fatal编程技术网

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回购协议上打开的一个旧版本。回过头来看,我的问题似乎与歧视联合有关,它与实现接口的类不按预期工作: