我有以下界面:
interface Person {
name: string;
id: number;
prop: number;
}
我想创建另一个扩展它的隔行扫描:
interface Person2 extends Person {
prop: string;
}
但是,我想覆盖prop
类型。我该怎么办?
答案 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;
}
这将使您可以选择将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";
}
答案 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;
}