【发布时间】:2019-03-13 08:48:48
【问题描述】:
我有如下界面:
interface Person {
name: string;
id: number;
prop: number;
}
我想创建另一个扩展它的交错:
interface Person2 extends Person {
prop: string;
}
但是,我想覆盖 prop 类型。我该怎么做?
【问题讨论】:
标签: typescript
我有如下界面:
interface Person {
name: string;
id: number;
prop: number;
}
我想创建另一个扩展它的交错:
interface Person2 extends Person {
prop: string;
}
但是,我想覆盖 prop 类型。我该怎么做?
【问题讨论】:
标签: typescript
由于消费者依赖于多态属性,因此您无法更改派生接口中的类型。您可能还需要考虑其他选项。
您可以缩小派生接口中的类型:
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;
}
这将使您可以选择应用 string 或 number 作为类型参数。
您还可以在此解决方案中使用类型保护:
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";
}
【讨论】:
你不能用接口做到这一点。
好吧,如果您可以访问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;
}
【讨论】:
您可以在扩展基础(超级)接口之前省略碰撞道具:
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;
}
【讨论】: