简体   繁体   中英

Typescript generic function with assertion about indexed type

I'm interested in having a function that can operate generically on any keyof T , but with an assertion that T[K] is of a specific type (ie string ). I think this is best illustrated by this code sample:

interface FooBar {
  x: string;
  y: number;
}

function foo<K extends keyof FooBar, ???>(propertyName: K, fooBar: FooBar) {
  const value = fooBar[propertyName];
  // I want the type of value to be `string`
}

What can I put in for ??? to have fooBar[propertyName] be typed as a string instead of a string | number string | number ? And I'd also like propertyName to only have a valid value of 'x' (obviously in practical circumstances there would be more than one string field, in which case it would be 'stringField1' | 'stringField2' etc.

Is this possible with TypeScript?

Thank you!

You can create a type that extracts only the keys from your source object that correspond to string values in that object

interface FooBar {
  x: string;
  y: number;
}

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

function foo<K extends StringKeys<FooBar>>(propertyName: K, fooBar: FooBar):string {
  const value = fooBar[propertyName];
  return value
} 

You don't have to explicitly have a type parameter for the property type typescript can infer it.

The StringKeys type works by creating a mapped type of [key]:[key] ('x':'x') for string valued properties and [key]:never ('y':never) for non string properties. The [keyof T] at the end will return all potential valeus for that objects properties. Never is special therefore excluded from this list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM