#typescript #api
Вопрос:
Допустим, у меня есть следующая полезная нагрузка:
{a: 1, b: 2, c: 3}
И я хочу иметь функцию, которая, учитывая объект, выбирает некоторые ключи и соответственно возвращает тип.
function pick<T>(obj: any, ...keys: string[]): T {
return (
Object.fromEntries(
keys
.filter(key => key in obj)
.map(key => [key, obj[key]])
)
) as T;
}
const test = { a: 1, b: 2, c: 3 };
type Foo = {
a: number,
b: number
}
const result = pick<Foo>(test, 'a', 'b');
console.log(result);
Есть ли способ справиться с этим лучше? Я понимаю, что использование принуждения к типу в значительной степени отключает систему безопасности машинописи.
Например, если я сделаю это:
console.log(pick<Foo>(test, 'b'));
Я говорю typescript, что функция pick возвращает объект Foo, но в нем не a
определен ключ.
Вариант использования заключается в том, что у нас есть вызовы API, которые мы:
- Придется печатать
- Нужно только ввести соответствующие ключи для нашего варианта использования
- Сделайте это в соответствии с лучшими практиками TS
Ответ №1:
Если вас устраивает реализация pick
без проверки типов, то вы можете, по крайней мере, выровнять все типы. Супер-удобный тип машинописи, который мы собираемся использовать для этого, на самом деле называется Pick
.
function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> {
return (
Object.fromEntries(
keys
.filter(key => key in obj)
.map(key => [key, obj[key]])
)
) as any;
}
Реализация функции точно такая же, за исключением того , что в конце мы выполняем перебор any
, что фактически говорит Typescript доверять нам. Pick<T, K>
это именно тот тип , который вам нужен: в нем говорится: «возьмите тип T
, подпишите его типом K
и посмотрите, что мы получим». K
является произвольным типом, который расширяется keyof T
. Предполагая, что вы передадите постоянные аргументы этой функции, вы получите объединение литералов типа "a" | "b"
for K
.
Я не знаю способа Object.fromEntries
проверить тип, если не считать перебора any
, как мы делали выше. По моему опыту, когда вы начинаете возиться с функциями на Object
прототипе, вам нужно немного подтолкнуть машинопись, чтобы получить правильные типы для вещей.