Home > front end >  How to verify that indexed type extends string?
How to verify that indexed type extends string?

Time:12-03

let's say I have function func with 2 generic arguments

const func = <T extends {}, K extends keyof T>() => {};

and a type

interface Form {
  a: boolean;
  b: string;
}

then I can invoke them like so without any errors

func<Form, "a">();
func<Form, "b">();

Now I want func to accept only keys for which T[K] = string In other words

func<Form, "a">(); // should pass
func<Form, "b">(); // should fail

My pseduo-typescript solution would be

const func = <T extends {}, K extends keyof T : where T[K] extends string>() => {};

but that of course doesn't go far. Is it even possible? Any help is appreciated.

CodePudding user response:

With a little helper type to get all the string types keys:

type StringKeys<T> = {
  [K in keyof T]:
    T[K] extends string ? K : never
}[keyof T]

type Test = StringKeys<{ a: boolean, b: string, c: string }>
// type: 'b' | 'c'

This utility type maps over all property of T, and if the value type extends string the key name is preserved, and otherwise it is discarded as never.

Then you simply use that like:

interface Form {
  a: boolean;
  b: string;
}

const func = <T, K extends StringKeys<T>>() => {};

func<Form, "a">(); // error
func<Form, "b">(); // fine

See Playground

  • Related