网站搜索

TypeScript 如何重写接口的属性类型


type Old = Other & {rewrite:number};
type New = Old & {rewrite:string};

预期行为:
New 的类型:Other & {rewrite:string}

实际行为:
New 的类型:Other & {rewrite:string & number}

答案#1

这是交叉类型的设计行为。如果该属性存在于交叉类型的两个成员上,则生成的属性类型将是原始类型的交叉类型。

要替换一个属性,我们可以首先使用 Pick 和 Exclude 将其从原始类型中排除:

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

type Other = { a: number };
type Old = Other & {rewrite:number};
type New = Omit<Old, 'rewrite'> & {rewrite:string};
let n: New;
n.rewrite // string 
n.a // number

如果这是一个常见的场景,我们甚至可以创建一个通用类型来进行替换:

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

type Other = { a: number };
type Old = Other & {rewrite:number, rewrite2:number};
type Replace<T, TKey extends keyof T, TKeyType> = Omit<T, TKey> & Record<TKey, TKeyType>
type New = Replace<Old, 'rewrite', string>   // replace one
type New2 = Replace<Old, 'rewrite' | 'rewrite2', string> // replace more