更新:
从 TypeScript 2.8 开始,条件类型更简洁地支持了这一点!到目前为止,这似乎也比以前的实现更可靠。
type Overwrite<T1, T2> = {
[P in Exclude<keyof T1, keyof T2>]: T1[P]
} & T2;
interface Person {
name: string;
hometown: string;
nickname: string;
}
type MakePersonInput = Overwrite<Person, {
nickname?: string;
}>
function makePerson(input: MakePersonInput): Person {
return {...input, nickname: input.nickname || input.name};
}
和以前一样,MakePersonInput 等价于:
type MakePersonInput = {
name: string;
hometown: string;
} & {
nickname?: string;
}
过时:
从 TypeScript 2.4.1 开始,似乎还有另一个选项可用,正如 GitHub 用户 ahejlsberg 在类型减法线程中所建议的那样:https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-307871458
type Diff<T extends string, U extends string> = ({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T];
type Overwrite<T, U> = { [P in Diff<keyof T, keyof U>]: T[P] } & U;
interface Person {
name: string;
hometown: string;
nickname: string;
}
type MakePersonInput = Overwrite<Person, {
nickname?: string
}>
function makePerson(input: MakePersonInput): Person {
return {...input, nickname: input.nickname || input.name};
}
根据 Intellisense,MakePersonInput 相当于:
type MakePersonInput = {
name: string;
hometown: string;
} & {
nickname?: string;
}
这看起来有点滑稽,但绝对可以完成工作。
不利的一面是,我需要盯着 Diff 类型一段时间,然后才能开始了解它是如何工作的。