如何描述应该接受某个结构的不同接口的接口?

时间:2018-10-02 01:57:41

标签: typescript

我需要函数来接收具有特定结构的接口的参数:它应该是字符串哈希或字符串哈希以及类似于这些对象的属性字符串哈希类型:

{
  anotherHash: {
    a: 'a',
    b: 'b'
    ...
  }
  c: 'c',
  d: 'd',
  ...
}

{
  anotherHash: {
    a: 'a',
    b: 'b',
    ...
  }
}

{
  c: 'c',
  d: 'd',
  ...
}

我尝试描述原始元素,但没有成功

interface IStringHash {
    [key: string]: string;
}

interface IModule {
    anotherHash?: IStringHash;
    [key: string]: string | IStringHash | undefined;
}

const myFunc(css: IModule): any => {...}

如果我尝试将具有真实接口的对象传递给函数

interface IModule1 {
    anotherHash: {
      ala: string
    };
    foo: string,
    bar: string
}

描述对象

const myObject: IModule1 = {
  anotherHash: {
    ala: 'boom'
  }
  foo: 'foo',
  bar: 'bar'
}

它会引发有关类型差异的错误:

Argument of type 'IModule1' is not assignable to parameter of type 'IModule'. Index signature is missing in type 'IModule1'. const myObject: IModule1

这里应该是元描述,但我不知道如何用打字稿来表达

这是play

1 个答案:

答案 0 :(得分:1)

IModuleIStringHash都定义了string索引器。这意味着可以使用任意字符串访问属性,从而可以添加随机属性。 IModule1不能通过任意键访问,它要求属性完全是指定的属性。

这是不兼容的根源。由于myFunc可以用随机的string进行索引,因此可能违反IModule1的约束。如果我们直接传递对象文字,则不会有问题,因为对象文字将扩展为包含索引签名:

MyFunction({
    anotherHash: {
        ala: 'boom'
    },
    foo: 'foo',
    bar: 'bar'
});

我们可以将索引签名添加到IModule1

interface IModule1 {
    anotherHash: {
        [key: string]: string;
        ala: string
    };
    foo: string,
    bar: string,
    [key: string]: string | IStringHash | undefined;
}

const myObject: IModule1 = {
    anotherHash: {
        ala: 'boom'
    },
    foo: 'foo',
    bar: 'bar'
}

MyFunction(myObject)

一种更复杂的方法,不需要添加字符串索引,将使用映射类型来表达约束:

type IStringHash<K extends string> = {
    [P in K]: string;
}

type IModule<T extends string, TOther extends string> = {
    [P in T]: "anotherHash" extends P ? IStringHash<TOther> : string;
}

const MyFunction = <T extends string, TOther extends string>(obj: IModule<T, TOther>): any => { 
    return "Hello World!"
}

interface IModule1 {
    anotherHash: {
        ala: string
    };
    foo: string,
    bar: string
}

const myObject: IModule1 = {
    anotherHash: {
        ala: 'boom'
    },
    foo: 'foo',
    bar: 'bar'
};

MyFunction(myObject)