strblr
strblr

Reputation: 950

How to tell typescript "An object with any key except those of that other type"

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

Answers (1)

kaya3
kaya3

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.)

Playground Link

Upvotes: 4

Related Questions