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

问题描述 投票:0回答:1

我正在尝试编写一些代码,对来自任意接口/类(作为通用参数提供)的一组字符串属性名称执行某些操作。

我的第一次尝试是这样的:

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

这会在以

const
:

开头的行中导致编译器错误

TS2322:键入“字符串|编号 | symbol' 不可分配给类型 'string'。
类型“数字”不能分配给类型“字符串”。

现在,第一行似乎很清楚了——

keyof T
可能是一个字符串,但也可能是一个数字,或者一个符号。

然而,第二行出乎我的意料——为什么编译器会假设

prop
是一个
number
而没有别的?或者它只是一个可能的、相互矛盾的案例的例子?

无论如何,我想我可以简单地限制我的循环体只处理那些字符串的属性名称:

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
被明确地说是字符串或数字或符号,那么在什么情况下 would 它根本就是一个字符串?


我的代码现在处于可以在 Jest 单元测试中运行的状态,并且 - 惊喜,惊喜 - 结果

prop
实际上 is 是一个字符串。它不能具有字符串类型的建议实际上是错误的。 (不幸的是,我无法关闭它,因为 WebStorm 不会泄露工具链中的哪个部分生成了消息。)

typescript webstorm typechecking
1个回答
0
投票

然而,第二行出乎我的意料——为什么编译器会假设 prop 是一个数字而不是别的?

这不是假设,它只是遍历了工会的所有可能性。 Typescript 考虑了

string
的情况,认为没有问题。然后它考虑它是
number
的情况,并且该情况会导致错误,因此它显示了这一点。
symbol
也会导致错误,但为了简洁起见,打字稿只显示它发现的第一个问题。

换句话说:第 2 行解释了 typescript 如何推断出第 1 行的错误

但是现在,我的类型检查条件 typeof prop === 'string' 被突出显示,并显示一条消息:

无效的“typeof”检查:“prop”不能有“string”类型

为什么 prop 永远不会是字符串?

这不是打字稿错误。例如,您不会在 this typescript playground 中看到它。这可能是一个 lint 错误。谷歌搜索让我找到了this question这可能是相关的。

© www.soinside.com 2019 - 2024. All rights reserved.