【问题标题】:Typescript - Generic Object type that always ends with string or numberTypescript - 始终以字符串或数字结尾的通用对象类型
【发布时间】:2021-11-25 21:05:46
【问题描述】:

在打字稿中是否有一种方法可以制作一个通用对象,它可以有很多层次,但仍然总是以字符串或数字属性值结尾。

interface GenericObject {
  [key: string]: string | number | GenericObject | GenericObject[];
}

const object: GenericObject = {
  test: 'test',
  testNum: 2,
  test2: {
    test: 'test'
  },
  test3: [
    {
      test: 'test'
    }
  ]
}

这样的东西在创建对象时可以正常工作,但在尝试访问属性时会引发错误。

object.test2.test;
object.test3[0].test;

类型'string | 上不存在属性'test'号码 |通用对象 | GenericObject[]'

有没有办法让这个工作,这样你就可以无限深层次,但总是以字符串或数字结尾?

游乐场网址 - https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgOIRNYCDyAjAKwgTGQG8BYAKGWQG0BrCATwC5kBnMKUAcwF12XHiF7IAPshABXALZ5oEtBiy5CxUpPSYeaoiTr8A3NQC+1aggD2ILsivqS7bavz7SAXnLVakLuwByPzAAgBofZGCAOTl2ACZwmkiILjj2SiTfFLBA4ICI00SsrgBmdjoI2gzaGuT-ZCDs-MzkcyT+MwsqB3cAOmC4-uyTbscwIdK6AAZ+CbAjIA

【问题讨论】:

    标签: typescript typescript-generics type-constraints


    【解决方案1】:

    我不是 TS 专家(目前)。但是,我认为你的定义没有错。

    问题在于,在 TS 中,您只能访问保证在联合类型的所有组成部分中的成员。

    因此,您遇到此类错误是有道理的。类型 number、string 和一些 GenericObject 接口之间没有足够的重叠。 TS 不知道 test2 变量是原始变量还是带有一些键的对象。

    告诉 TS 什么是 test2 或 test3 道具的一种方法(在访问的地方)是remap the key via as

    (object.test2 as GenericObject).test;
    
    

    并保留object: GenericObject 原样。只是我的两分钱。我很高兴看到其他人建议作为您问题的解决方案(无限深的对象)。

    【讨论】:

    • 是的,这与我提出的解决方案类似。想知道是否有更好的解决方法。
    【解决方案2】:

    如果你想同时拥有:限制和属性推断,你只需要使用额外的功能。

    interface GenericObject {
      [key: string]: GenericObject | GenericObject[] | string | number
    }
    
    const validation = <Obj extends GenericObject>(obj: Obj) => obj
    
    const result = validation({
      test: 'test',
      testNum: 2,
      test2: {
        test: 'test'
      },
      test3: [
        {
          test: [{ a: 's' }]
        }
      ]
    })
    
    result.test2.test // ok
    
    
    const withError = validation({
      test: 'test',
      testNum: 2,
      test2: {
        test: 'test'
      },
      test3: [
        {
          test: [{ a: false }] // <--- expected error
        }
      ]
    })
    
    

    Playground

    【讨论】:

      猜你喜欢
      • 2023-02-06
      • 2017-03-31
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      • 2010-11-18
      • 2016-07-17
      • 2017-11-13
      相关资源
      最近更新 更多