当使用负映射类型时,它似乎正在从属性中删除修饰符。我认为这是由排除类型引起的,但我不知道为什么。
我希望减号只是从t中删除u的键,而不更改t的属性修饰符。
type Minus<T, U> = { [P in Exclude<keyof T, keyof U>]: T[P] }
type Noop<T> = { [P in keyof T]: T[P] }
interface Student {
readonly gpa: number
hobby?: string
name: string
}
interface Person {
name: string
}
type Difference = Minus<Student, Person>
// type Difference = {
// gpa: number; <-- Where did readonly go?
// hobby: string | undefined; <-- Why is it no longer optional? It seems to have picked up '| undefined' though...
// }
const test1: Difference = { gpa: 4 } // <-- Error: property 'hobby' is missing
type NoopType = Noop<Student>
// type StringsOnly = {
// readonly gpa: number;
// hobby?: string | undefined;
// name: string;
// }
const test2: NoopType = { gpa: 4, name: "bob" } // OK
最佳答案
typescript将保留同态映射类型的修饰符,如here所述,但基本思想是,如果类型具有{ [P in keyof T]: T[P] }
或类似的形式,则保留修饰符。在你的情况下,编译器不承认映射类型是同态的,因为Exclude<keyof T, keyof U>
,我很确定这个限制被记录在某个地方,但是目前我不能把它限制。解决这个问题的简单方法是通过Pick
使用额外的间接寻址,例如:+
type Minus<T, U> = Pick<T, Exclude<keyof T, keyof U>>