Restrict generic key type based on lookup type in TypeScript

浪尽此生 提交于 2021-01-29 06:15:50

问题


I'm working on a function that takes two type parameters, T and K. T extends a Record type and K is a key of the first type. Is there a way I can restrict the key type based on its lookup type (T[K]) in T?

I have the following types:

type FormValue = string | number | boolean | null;

type FormValues = Record<string, FormValue>;

and the following function:

function numericFormHelperFunc<T extends FormValues, K extends keyof T>(key: K, formValues: T) {}

Is there a way I can restrict which keys can be used for this function so that only keys in formValues that have lookup types of, say, number are allowed? Basically a way to assert that T[K] extends number.

For example if I have this example form type:

type MyFormValues = {
    name: string;
    age: number;
    numPets: number;
}

Can I add a type restriction to numericFormHelperFunc so that only the keys "age" and "numPets" could be used?

I'm looking for a static way to do this so that I'll get editor warnings about trying to use numericFormHelperFunc("name", myFormValues). Also would like for typescript to know that the value from looking up key in formValues is of a specific type, rather than just T[K] (e.g. so that number-specific methods and operators can be used without type assertions).


回答1:


Here is the solution:

type FormValue = string | number | boolean | null;

type FormValues = Record<string, FormValue>;

type MyFormValues = {
  name: string;
  age: number;
  numPets: number;
}

/**
 * Takes two arguments,
 * T - indexed type
 * Allowed - allowed types
 * 
 * Iterates through all properties and check
 * if property extends allowed value
 */
type Filter<T, Allowed> = {
  [P in keyof T]: T[P] extends Allowed ? P : never
}[keyof T]

function numericFormHelperFunc<T extends FormValues>(key: Filter<MyFormValues, number>, formValues: T) { }

numericFormHelperFunc('age', {'sdf':'sdf'}) // ok
numericFormHelperFunc('numPets', {'sdf':'sdf'}) // ok
numericFormHelperFunc('hello', {'sdf':'sdf'}) // error
numericFormHelperFunc('2', {'sdf':'sdf'}) // error
numericFormHelperFunc('name', {'sdf':'sdf'}) // error


来源:https://stackoverflow.com/questions/65241412/restrict-generic-key-type-based-on-lookup-type-in-typescript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!