Ввод функции на основе значения аргумента

Предположим, у меня есть следующая функция JS:

function extractProperty(propName) {
    return x => x[propName];
}

Могу ли я напечатать extractProperty с.т. по выводу типа Typescript я получаю следующее:

const x = { first: 1, second: "two" };
const y = { first: [1], second: 2 };
// or any other object having first and second

const a1 = extractProperty("first")(x); // a1 should be of type number
const a2 = extractProperty("second")(x); // a2 should be string
const a3 = extractProperty("first")(y); // a3 should be number[]
const a4 = extractProperty("second")(y); // a4 should be number

const getFirst = extractProperty("first");
// getFirst should be <T> (t: T) => T["first"]

const getSecond = extractProperty("second");
// getSecond should be <T> (t: T) => T["second"]

Если бы вместо параметра propName у меня было фиксированное имя свойства, я, вероятно, мог бы сделать следующее:

function extractPropertyFirst ():
<TFirst> (x: { first: TFirst }) => TFirst

или, чуть больше в направлении того, чего я хочу достичь,

function extractPropertyFirst ():
<T> (x: T) => T["first"]

Но как заставить машинописный текст принимать аргумент функции в качестве имени свойства?

Я играл со следующим подходом, но безуспешно:

function getProperty<K> (propName: K):
<TProp> (t: { [K]: TProp }) => TProp {
    return x => x[propName];
}

Typescript не принимает общий K в качестве типа индексации.

В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Прошлая статья была первой из цикла статей о создании системы электронной коммерции с использованием Keystone.js, и она была посвящена главным образом...
2
0
44
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете заставить getProperty работать, используя {[Key in K]: TProp} или, что то же самое, Record<K, TProp> для типа t и добавив ограничение K extends PropertyKey:

function extractProperty<K extends PropertyKey>( propName: K):
  <TProp>(t: Record<K, TProp>) => TProp {
    return (x) => x[propName];
  }

const a1 = extractProperty("first")(x);
// type: number

const a2 = extractProperty("second")(x)
// type: string

const a3 = extractProperty("first")(y);
// type: number[]

const a4 = extractProperty("second")(y);
// type: number

Площадка TypeScript

Спасибо. Это было быстро! Я не знал о PropertyKey до сих пор.

JohnB 22.04.2022 23:37

Извините, еще вопрос: Почему Record<K, TProp> работает, а { [K]: TProp } нет?

JohnB 22.04.2022 23:41

Второй тип объявляет объект с вычисляемым свойством K, где K — это значение, а не тип. Использование вместо этого значения (т. е. {[propName]: TProp}) также не будет работать, поскольку выражения ключа вычисляемого свойства не могут иметь универсальных типов.

Oblosys 23.04.2022 00:02

Другие вопросы по теме

Похожие вопросы

Передача vscode во внешние функции
Firebase: Почему мой код использует только первый документ в моей коллекции?
Реагировать на ошибку машинописного текста - элемент неявно имеет любой тип, потому что выражение строки типа не может использоваться для индексирования типа {}
Как получить доступ к вложенным необязательным индексам из интерфейса
Почему машинописный текст не может контекстуально вывести эти типы промежуточного программного обеспечения
Передать конструктор класса как функцию в другом классе
React & clsx: добавьте имя класса, если текущий элемент в сопоставленном массиве является первым из нескольких элементов
Свойство «MathFun» отсутствует в типе «(x?: число, y?: число) => число», но требуется в типе «Func».
Получение строки типа не может быть назначено строке типа для компонента TS в сборнике рассказов
Как ввести useState для файлов?