打字稿覆盖超级接口属性不起作用

时间:2019-03-13 08:48:48

标签: typescript

我有以下界面:

interface Person {
  name: string;
  id: number;
  prop: number;
}

我想创建另一个扩展它的隔行扫描:

interface Person2 extends Person {
  prop: string;
}

但是,我想覆盖prop类型。我该怎么办?

3 个答案:

答案 0 :(得分:2)

由于使用者依赖于多态属性,因此无法在派生接口中更改类型。您可能还需要考虑其他选择。

可以在派生界面中缩小类型:

interface Person {
  name: string;
  id: number;
  prop: number | string;
}

interface Person2 extends Person {
  prop: string;
}

interface Person3 extends Person {
  prop: number;
}

然后您可以使用类型防护来检查prop的实际类型:

function isPerson2(value: Person): value is Person2 {
    return typeof value.prop === "string";
}

function isPerson3(value: Person): value is Person3 {
    return typeof value.prop === "number";
}

function doSomething(value: Person) {
    if (isPerson2(value)) {
        //value is of type Person2 in here
    }
}

另一种选择是使Person通用:

interface Person<T> {
  name: string;
  id: number;
  prop: T;
}

这将使您可以选择将stringnumber用作类型参数。

您也可以在此解决方案中使用类型防护:

function isPersonWithString(value: Person<string | number>): value is Person<string> {
    return typeof value.prop === "string";
}

function isPersonWithNumber(value: Person<string | number>): value is Person<number> {
    return typeof value.prop === "number";
}

答案 1 :(得分:1)

您不能使用界面执行此操作。

好吧,如果您可以访问Person界面,则可以进行的操作。只需将其分为两部分:

interface PersonBase {
  name: string;
  id: number;
}

interface Person extends PersonBase {
  prop: number;
}

interface Person2 extends PersonBase {
  prop: string;
}

如果您不能更改原始界面并且不需要此,这是替换现有类型中的现有密钥的技巧:

type Person2 = Pick<Person, Exclude<keyof Person, 'prop'>> & {prop: string};

或者,如果映射的类型看起来更清晰:

type Person2 = {
  [K in Exclude<keyof Person, 'prop'>]: Person[K]
} & {
  prop: string;
}

答案 2 :(得分:1)

您可以在扩展基础之前忽略base(super)接口中的碰撞道具:

interface Person {
    name: string;
    id: number;
    prop: number;
}

type Omit<T, TKey extends keyof T> = Pick<T, Exclude<keyof T, TKey>>;

interface Person2 extends Omit<Person, 'prop'> {
    prop: string;
}