Можно ли сопоставить тип записи с типом функции, используя сопоставленные условные типы?

Учитывая следующий тип в Typescript

type MyType = {
    foo: int,
    bar: string
}

могу ли я определить сопоставление (предпочтительно с использованием сопоставленных условных типов), чтобы получить

type MyTypeFn = (foo: int, bar: string) => MyType

person robkuz    schedule 31.03.2018    source источник
comment
это number, а не int, но независимо от этого, я не думаю, что есть способ сделать это, в машинописном тексте нет сопоставленных функций. Вы можете определить type Create<T> = (o:T) => T, но это не добавляет большого значения..   -  person Titian Cernicova-Dragomir    schedule 31.03.2018


Ответы (1)


Не совсем. Невозможно перечислить ключи объекта в каком-либо предсказуемом или пригодном для использования порядке. Вы можете сделать что-нибудь программным, но начинать нужно с более удобного для манипулирования типа, например:

type MySchema = [['foo', number], ['bar', string]]

который представляет собой кортеж из двух кортежей, представляющих пары ключ-значение в вашем типе. Затем вы можете синтезировать MyType, используя функцию типа (TSv2.8 и выше), например:

type MakeMyType<S extends [string, any][], M = S[number]> = 
  { [K in S[number][0]]: M extends [K, any] ? M[1] : never }

что вы можете проверить:

type MyType = MakeMyType<MySchema>
// inspects as { foo: number; bar: string }

И затем вы можете синтезировать MyTypeFn, используя функцию типа, такую ​​как:

type MakeMyFunction<S extends [string, any][], L = S['length'], T = MakeMyType<S>> =
  L extends 0 ? () => T :
  L extends 1 ? (a0: S[0][1]) => T :
  L extends 2 ? (a0: S[0][1], a1: S[1][1]) => T :
  L extends 3 ? (a0: S[0][1], a1: S[1][1], a2: S[2][1]) => T :
  L extends 4 ? (a0: S[0][1], a1: S[1][1], a2: S[2][1], a3: S[3][1]) => T :
  L extends 5 ? (a0: S[0][1], a1: S[1][1], a2: S[2][1], a3: S[3][1], a4: S[4][1]) => T :
  L extends 6 ? (a0: S[0][1], a1: S[1][1], a2: S[2][1], a3: S[3][1], a4: S[4][1], a5: S[5][1]) => T :
  (...args: S[number][1][]) => T

Обратите внимание, что не существует программного способа создания списков аргументов переменной длины, поэтому лучшее, что вы можете сделать, — это создавать случаи до некоторой фиксированной максимальной длины, как указано выше. Давайте проверим:

type MyTypeFn = MakeMyFunction<MySchema>
// inspects as (a0: number, a1: string) => { foo: number; bar: string; }

И да, имена параметров также теряются (foo и bar становятся a0 и a1). Это не влияет на совместимость типов сигнатуры функции, где имена параметров не важны. Но я предполагаю, что вам нужны эти имена параметров для подсказок при использовании или реализации функции. Если так, то это еще одно "не совсем".

Так что это долгий и растянутый способ несколько раз сказать «не совсем». Ну ладно, может быть, это все-таки помогло. Удачи!

person jcalz    schedule 31.03.2018