TypeScript对象结构同名不能类型使用typeof做类型保护的问题


interface Foo {
    kind: 'foo';
    diffType: string;
    fooOnly: boolean;
    shared: number;
}
interface Bar {
    kind: 'bar';
    diffType: number;
    barOnly: boolean;
    shared: number;
}
function handle(input: Foo | Bar2) {
    // 报错,并没有起到区分的作用,在两个代码块中 input 都是 Foo | Bar
    if (typeof input.diffType === 'string') {
        input.fooOnly; //类型“Foo | Bar”上不存在属性“fooOnly”。类型“Bar”上不存在属性“fooOnly”。
    } else {
        input.barOnly; // 类型“Foo | Bar”上不存在属性“barOnly”。类型“Foo”上不存在属性“barOnly”
    }
}

Foo和Bar的diffType是不同的ts类型,为什么用。typeof input.diffType === “string",无法分辨Foo和Bar呀?

这是因为 typeof 运算符在编译时进行类型推断,但在运行时仅仅返回字符串("string" 或 "number")。所以,在每个分支内,编译器仍然认为 input 的类型为 Foo | Bar,因此无法访问任何类型特定的属性。

要解决此问题,可以使用类型断言:

if (typeof input.diffType === 'string') {
    (input as Foo).fooOnly;
} else {
    (input as Bar).barOnly;
}