在 TypeScript 接口中描述属性对象

Posted

技术标签:

【中文标题】在 TypeScript 接口中描述属性对象【英文标题】:Describe property object in TypeScript interface 【发布时间】:2017-08-08 10:35:04 【问题描述】:

我想描述一些嵌套对象的接口。在不为嵌套对象创建接口的情况下如何做到这一点?

interface ISome 
  strProp:string;
  complexProp:
    someStrKeyWhichIsDynamic:
      value:string;
      optValue?:string;
    
  ;

我也试过了(UPD:其实没关系

interface ISome 
  strProp:string;
  complexProp:
    [someStrKeyWhichIsDynamic:string]:
      value:string;
      optValue?:string;
    
  ;

但我不能分配像这样的对象

let dynamicStrKey = 'myKey';
  
   strProp:'str', 
   complexProp:
     [dynamicStrKey]:
       value:'something here',
       optValue: 'ok, that too',
    
  ;

到带有ISome 类型的变量,没有类型断言<ISome>。至少 WebStorm 将此分配突出显示为错误。

如何正确描述嵌套对象?

【问题讨论】:

【参考方案1】:

最后,我认为我的第二个变体是正确的

interface ISome 
  strProp:string;
  complexProp:
    [someStrKeyWhichIsDynamic:string]:
      value:string;
      optValue?:string;
    
  ;

对于动态键,您可以只写[dynamic:string] 来指定这里将是一些字符串属性。好像我遇到了与问题无关的 webstorm 错误。

顺便说一句,如果你有一些基于字符串的枚举,你可能想要使用[key in MyEnum]: ... 而不是[key:string]。这解决了错误:

TS1337 索引签名参数类型不能是联合类型。

如果你有一个文字对象,例如 const obj = prop1: 'blah', prop2: 'blahblah'

您可能想使用[key in keyof typeof obj]: ... 来描述您的动态键只能是“prop1”或“prop2”(或者,更通用的,来自Object.keys(obj 的值)

【讨论】:

【参考方案2】:

你的前两个例子没有错。他们都编译得很好,并且是他们所说的。

在您的第三个示例中,您显然希望属性名称是“动态的”。但请记住,TS 在编译时运行。在编译时,dynamicStrKey 还没有值。因此,试图将其用作类型定义中的属性名称是没有意义的。您不能使用运行时值定义编译时工件。

【讨论】:

但是如果我想拥有动态属性,我应该如何描述呢?我想指定这里将是一些属性,它应该是一个字符串,它应该有一些对象值,这也是描述的。 正如我所说,如果我正确理解了您的问题,您无法定义编译时 TS 类型,其属性的值直到运行时才知道。【参考方案3】:

第二部分的代码是支持动态属性。你不能和最后一个一起使用,因为类型不会发送到 javascript 代码。我想你只是喜欢下面的东西,使用泛型代替。更多细节,你可以看打字稿index types。

interface ISome<K extends string> 
    strProp: string;
    complexProp: 
        [P in K]: 
            value: string;
            optValue?: string;
        
    ;



let foo: ISome<"foo"> = 
    strProp:"foo",
    complexProp:
        foo:
            value:"foo"
        
    
;

let bar: ISome<"bar"> = 
    strProp:"bar",
    complexProp:
        bar:
            value:"bar",
            optValue:"<optional>"
        
    
;

let foobar: ISome<"foo"|"bar"> = 
    strProp:"foo",
    complexProp:
        foo:
            value:"foo"
        ,
        bar:
            value:"bar",
            optValue:"<optional>"
        
    
;

// interesting things that use with any|never types
let anything:ISome<any|never>=
    strProp:"foo",
    complexProp:
;

【讨论】:

以上是关于在 TypeScript 接口中描述属性对象的主要内容,如果未能解决你的问题,请参考以下文章

如何获取与 Typescript 中的接口匹配的对象的所有属性? [复制]

TypeScript 中的类和接口

如何使用 TypeScript 在接口中定义对象的命名数组?

Typescript接口,强制执行额外属性的类型[重复]

使用带有递归 JSON 的 Typescript 接口

带有属性的函数的 TypeScript 接口