typescript 为什么我的属性名不能是字符串类型?

hts6caw3  于 2023-03-31  发布在  TypeScript
关注(0)|答案(1)|浏览(155)

我正在尝试编写一些代码,对来自任意接口/类(作为泛型参数提供)的一组字符串属性名称执行一些操作。
我的第一次尝试看起来像这样:

function doSomething<T extends object>(props: (keyof T)[]) {
    for (let prop of props) {
        const x: string = prop;
    }
}

这会导致以const开头的行中出现编译器错误:
TS 2322:键入“字符串|号码|symbol'不能分配给类型' string '。
类型“number”不能赋给类型“string”。
现在,第一行看起来很清楚-keyof T可能是一个字符串,但也可能是一个数字或符号。
然而,第二行让我意想不到的是--为什么编译器会认为propnumber而不是别的?或者这只是一个可能的冲突情况的例子?
在任何情况下,我想我可以简单地限制我的循环体,只处理那些字符串属性名:

function doSomething<T extends object>(props: (keyof T)[]) {
    for (let prop of props) {
        if (typeof prop === 'string') {
            const x: string = prop;
        }
    }
}

但是现在,我的类型检查条件typeof prop === 'string'被突出显示,并显示一条消息:
无效的“typeof”检查:“prop”不能具有类型“string”
为什么prop不能是字符串呢?当我用一个示例类调用我的函数时,我当然可以传递一个字符串数组(显然,只要这些字符串匹配示例类的属性名)。
或者这些字符串隐式地转换为symbol?事实上,如果我将类型检查条件更改为typeof prop === 'symbol',就不会再警告这将永远不会匹配。但是,在第一条错误消息中,keyof T被显式地说成是字符串、数字或符号,那么在什么情况下它会是字符串呢?
我的代码现在处于可以在Jest单元测试中运行的状态,令人惊讶的是,prop实际上是一个字符串。它不能有类型string的建议实际上是错误的。(不幸的是,我不能关闭它,因为WebStorm没有给予工具链中的哪一部分生成了消息。)
这可能与bug WEB-49787有关。

l2osamch

l2osamch1#

然而,第二行出乎我的意料--为什么编译器会假设prop是一个数字,而不是其他任何东西?
这不是假设,它只是遍历了联合的所有可能性。Typescript考虑了它是string的情况,并且没有发现问题。然后它考虑了它是number的情况,并且这一情况导致错误,因此它表明. symbol也会导致错误,但为了简洁起见,Typescript只显示它发现的第一个问题。
换句话说:第2行解释了typescript如何推断出第1行的错误
但是现在,我的类型检查条件typeof prop === 'string'被突出显示,并显示一条消息:
无效的“typeof”检查:“prop”不能具有类型“string”
为什么prop不能是字符串呢?
这不是一个 typescript 错误。例如,你不会看到它在这个 typescript 操场。这可能是一个lint错误。谷歌搜索导致我this question,这可能是相关的。

相关问题