首页 > 解决方案 > Typescript keyof T 类型断言与类型注释

问题描述

我试图了解这是类型断言的预期工作机制还是编译器错误。

这是用例:

interface IExample {
    one: string;
    two: number;
}

interface IGeneric<T> {
    example: [key: keyof T, someText: string][]; // tuple array
}

这些是 3 个示例及其各自的错误消息。1 和 2 似乎按预期工作,但令我惊讶的是 example3 的行为与 example1 不同?

// Type '"three"' is not assignable to type 'keyof IExample'.(2322)
let example1: IGeneric<IExample> = { example: [
    ['one', 'one'],
    ['three', 'three'],
]};


/*
Conversion of type '{ example: (["three", string] | ["four", string])[]; }' to type 'IGeneric<IExample>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Types of property 'example' are incompatible.
    Type '(["three", string] | ["four", string])[]' is not comparable to type '[key: keyof IExample, someText: string][]'.
      Type '["three", string] | ["four", string]' is not comparable to type '[key: keyof IExample, someText: string]'.
        Type '["four", string]' is not comparable to type '[key: keyof IExample, someText: string]'.
          Type at position 0 in source is not compatible with type at position 0 in target.
            Type '"four"' is not comparable to type 'keyof IExample'.

*/
let example2 = { example: [
    ['three', 'three'],
    ['four', 'four'],
]} as IGeneric<IExample>;


// no error ??
let example3 = { example: [
    ['one', 'one'],
    ['three', 'three'],
]} as IGeneric<IExample>;

标签: typescript

解决方案


您应该将其as视为一种抑制类型错误的方法;当您比编译器更清楚某事物的类型时,或者当您为了方便而想对编译器撒谎时,您可以使用它。因此,当您as在第三个示例中使用时没有出现类型错误并不奇怪;这as就是应该做的。

真正的问题是为什么您的第二个示例确实给出了类型错误。本质上,这是因为在您的第三个示例中,推断类型与断言类型有一些重叠,而在您的第二个示例中,与断言类型没有重叠。该as关键字旨在告诉编译器一种类型的值实际上是不同的类型,但如果这两种类型根本没有重叠,那么编译器仍然会给出错误,因为你断言的不仅仅是假,这在逻辑上是不可能的。*

* 学究式注意:从技术上讲,这两种类型根本不完全没有重叠,因为具有空数组的对象{example: []}可以分配给这两种类型。尽管如此,同样的理由也适用。如果类型有足够的重叠,编译器愿意“相信你的话”,但如果重叠太小以至于你可能犯了错误,它仍然会出错。


推荐阅读