首页 > 解决方案 > 我可以在打字稿中使用什么来显示两个接口的值之间的关系

问题描述

interface baseVal {
    val: string
}

interface parentA{
    checker: baseVal
}

interface parentB{
    someone: baseVal
}

let test = <T extends parentA | parentB>(param: T) => {
    const keys = Object.keys(param) as (keyof T)[]
    keys.forEach(key => {
        let data = param[key] as baseVal // error 

    })
}

我目前在“let data = param [key] as baseVal”处遇到错误这是错误状态:

将 'T[keyof T]' 类型转换为 'baseVal' 类型可能是一个错误,因为这两种类型都没有与另一种充分重叠。如果这是故意的,请先将表达式转换为“未知”。

为什么打字稿不明白接口中的值都是相同的类型?如何创建接口以便打字稿知道这种关系?

标签: javascripttypescript

解决方案


实际上,当您键入 parentA | 时会发生什么?parentB 是一种根本没有键的类型,因为联合(管道)的行为与您在接口情况下所期望的不同。请参阅https://www.typescriptlang.org/docs/handbook/advanced-types.html#union-types

如果一个值的类型为 A | B,我们只知道它有 A 和 B 都有的成员。在此示例中,Bird 有一个名为 fly 的成员。我们不能确定变量类型是否为 Bird | 鱼有飞法。如果变量在运行时确实是 Fish,则调用 pet.fly() 将失败

您可以通过输入一行来验证这一点let x = param.someone.val;。你会看到param没有成员的智能感知抱怨someone。那是因为param 可能是 parentA 类型,在这种情况下,该行将在运行时抛出异常,因为param.someone未定义。所以简而言之,你不能在这里使用联合类型。

typescript 的主要目的之一是防止由于输入错误导致的运行时错误,因此如果传递给函数的对象可能是两种类型之一,则您不能访问仅属于其中一种类型的字段。在某些情况下,您可以在这种情况下使用链接页面上描述的类型检查,但在您的情况下,问题并不那么容易解决。请注意,您遍历param. 想象一下,如果这些类型有多个键。typescript 将如何解析 param[key] 的类型?在提供的代码中,人们可以看到类型是什么,但一般来说,这种方法是无效的。因此,如果您想大致保留代码,您可能需要使用以下内容:

interface baseVal {
    val: string
}

interface parentA{
    checker: baseVal;
}

interface parentB{
    someone: baseVal;
}

interface parent {
  [key: string]: baseVal;
}

let test = <T extends parent>(param: T) => {
    const keys = Object.keys(param) as (keyof T)[]
    keys.forEach(key => {
        let data = param[key] as baseVal; 
    })
} 

(请注意,如果您的实际类型有更多不同类型的键,这将不合适,但是您的代码无论如何都是无效的。)


推荐阅读