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?
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.)
Playground Link
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With