0

I would like to do:

type PossibleKeys = 'a' | 'b' | 'c'

... and now I would like to create a type which the key has to be necessarily one of the above. Like:

type MyType = {
 a: number;
 b: string;
 c: boolean;
 d: {} // <--- I want it not to be allowed because `d` does not extend `PossibleKeys`
}

How would you do that?

3
  • What's the use case? Commented Dec 10, 2021 at 15:48
  • not sure what you're asking here. Do you want to restrict the type definition or create a type that restricts instances based on PossibleKeys. Commented Dec 10, 2021 at 17:27
  • type MyType = Record<PossibleKeys, unknown> Commented Dec 10, 2021 at 17:52

1 Answer 1

5

You can create "type validators" using the pattern T extends (Condition ? unknown : never)

type ValidateKeys<
    K,
    T extends ([keyof T] extends [K] ? [K] extends [keyof T] ? unknown : never : never)
> = T

type PossibleKeys = 'a' | 'b' | 'c'

type MyType = ValidateKeys<PossibleKeys, {
    a: number;
    b: string;
    c: boolean;
}>

playground

Sign up to request clarification or add additional context in comments.

3 Comments

Amazing! FWIW this also works without the tuple syntax i.e., T extends keyof T extends K ? (K extends keyof T ? unknown : never) : never
How to trigger autocompletion when using ValidateKeys in VSCode ?
@vikyd I think we do need the tuple wrapping to avoid the distribution of conditional types over unions. Demo: type T1<T> = T extends 'a' ? 1 : 0; type R1 = T1<"a" | "b">; type T2<T> = [T] extends ['a'] ? 1 : 0; type R2 = T2<"a" | "b">;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.