Reputation: 950
I want to define a type allowing any key except those of another type:
type A = { x: number, y: number }
type B = { /* Any key except those in A */ }
let foo: B = { z: 12 } // Good
let bar: B = { z: 12, y: 13 } // Bad
I've tried this but it doesn't work:
type B = { [key: Exclude<string, keyof A>]: any }
How can I define B
?
Upvotes: 3
Views: 2970
Reputation: 51034
The following definition works: the first part says it can have any properties with any types, and the second part says that it doesn't have to have any properties in keyof A
, but if it does have any such properties, then their types must be never
(or undefined
).
type B = { [k: string]: any } & { [K in keyof A]?: never }
Your "good" code type-checks as required, and your "bad" code fails with the type error Type 'number' is not assignable to type 'undefined'.
.
The type { [k: string]: any }
is very weak, but you can write a stricter type there if you wish. It may be useful to define a generic type to exclude the properties of one type from another:
type ExcludeProps<S, T> = S & { [K in keyof T]?: never }
Note that the excluded properties can still be present with the value undefined
, unless the exactOptionalPropertyTypes
flag is enabled. (This flag is not included in strict
mode, you must enable it separately.)
Upvotes: 4