Я работаю над функцией, которая принимает два параметра типа, T
и K
. T
расширяет тип Record
, а K
является ключом первого типа. Есть ли способ ограничить тип ключа на основе его типа поиска (T[K]
) в T
?
У меня есть следующие типы:
type FormValue = string | number | boolean | null;
type FormValues = Record<string, FormValue>;
и следующая функция:
function numericFormHelperFunc<T extends FormValues, K extends keyof T>(key: K, formValues: T) {}
Есть ли способ ограничить, какие клавиши можно использовать для этой функции, чтобы были разрешены только клавиши в formValues
, которые имеют типы поиска, скажем, number
? В основном способ утверждать, что T[K] extends number
.
Например, если у меня есть этот пример типа формы:
type MyFormValues = {
name: string;
age: number;
numPets: number;
}
Могу ли я добавить ограничение типа к numericFormHelperFunc
, чтобы можно было использовать только ключи "age"
и "numPets"
?
Я ищу статический способ сделать это, чтобы получать предупреждения редактора о попытке использовать numericFormHelperFunc("name", myFormValues)
. Также хотелось бы, чтобы машинописный текст знал, что значение при поиске key
в formValues
имеет определенный тип, а не просто T[K]
(например, чтобы числовые методы и операторы можно было использовать без утверждений типа).
Вот решение:
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
Для понимания, причина, по которой это работает, заключается в том, что AnyType | never === AnyType
.
Это плюс строка [keyof T]
в конце, да.
Определенно касается основного вопроса моего вопроса, спасибо. Для этого может потребоваться открыть отдельный вопрос, но есть ли способ сообщить редактору о базовом типе при использовании типа поиска? В этом случае было бы неплохо иметь возможность обрабатывать значение для данного ключа как number
без необходимости делать какие-либо утверждения типа. Это возможно?
Кажется, это возможно, если использовать фактический тип FormValues
, но не с T extends FormValues
(по крайней мере, без дополнительной обработки).
Не уверен, что это возможно
Это нормально для вас typescriptlang.org/play?ts=3.9.7#code/… ?