【问题标题】:Typescript compiler failing with different property types on Omit and index signatureTypescript 编译器因省略和索引签名上的不同属性类型而失败
【发布时间】:2021-08-05 02:06:34
【问题描述】:

我正在尝试使用省略了属性的子类型,并使用通用索引签名将其分配给其父类型。我试图理解为什么它会让这种情况发生只有属性是相同的类型。

例如,这一切都很好:

interface Obj {
  foo: number
  bar: number
  baz: number
}
type Sub = Omit<Obj, "baz">

let obj: Obj = {foo: 1, bar: 1, baz: 1}

function fn <K extends keyof Sub>(key: K, val: Sub[K]) {
  obj[key] = val
}

在这个问题上,编译器抱怨“类型'Sub[K]'不可分配给类型'Obj[K]'。 “Sub”类型中缺少属性“baz”,但在“Obj”类型中是必需的”

interface Obj {
  foo: number
  bar: string
  baz: number
}

感谢您的帮助!

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    在您的示例中,keyof Sub 因此K 的类型为"foo" | "bar"。这意味着Sub[K]string | number 类型;键为“foo”和“bar”的条目包含的值的类型。

    string | number 不是一个可以分配给任何有用的东西的类型。我确信有一个替代解决方案可以解决您想要完成的任务,但就目前的情况而言,这似乎是一个 XY 问题。

    更新:我上面所说的虽然是对的,但没有抓住问题的重点。为了在 cmets 中进行对话,我将保留此内容,以防万一帮助其他人找到正确的答案。

    【讨论】:

    • 嗨,内森,感谢您的回复。我知道 Sub[K] 从字符串切换到字符串 |数字。 Typescript 可以通过在省略之前使用密钥来处理推断类型,所以我不明白为什么在省略之后它无法使用相同的逻辑。该应用程序循环遍历对象上具有不同类型的一长串属性,然后根据它们的类型以不同的方式处理值,这是正确处理它的唯一方法。我可以将密钥转换为父(Obj)模式,它工作得很好(这也是 string | number ),但这只是一个hack
    • 可以!非常酷,我没有意识到 TS 可以做到这一点。您还可以将obj 转换为Sub,这可能会更干净一些,感觉不那么老套。
    • 这会让事情变得更容易,不幸的是,我正在尝试获取父对象的子对象,并使用那个较小的对象来填充较大的对象。开始认为这可能是打字稿中实用程序类型的错误。或者也许在我不知道的地方有免责声明
    猜你喜欢
    • 2023-04-10
    • 2021-07-06
    • 1970-01-01
    • 2021-12-08
    • 2019-05-01
    • 2020-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多