TypeScript общие c параметры типа выводятся с помощью функций, но не типа? - PullRequest
2 голосов
/ 29 марта 2020

Учтите это:

type SpecificKeys<T extends string> = {
  [key in T]: string;
};

const foobar: SpecificKeys<"foo" | "bar"> = {
  foo: "foo",
  bar: "bar",
};

Я должен указать объединение ключей в качестве аргумента типа generi c при создании foobar, который является избыточным. Я не могу понять, как обойти это. Но если я напишу функцию бездействия:

function makeSpecificKeys<T extends string>(thing: SpecificKeys<T>): SpecificKeys<T> {
  return thing;
}

const foobarInferred = makeSpecificKeys({
  foo: "foo",
  bar: "bar",
});

, тогда const foobarInferred будет правильно напечатан как SpecificKeys<"foo" | "bar">, и мне не пришлось повторяться, перечисляя все ключи.

Есть ли способ добиться вывода параметра типа generi c при создании типизированной переменной без необходимости делать функцию бездействия?

1 Ответ

0 голосов
/ 30 марта 2020

Ответ - нет. Тип ограничивает значение, говоря, a:T означает, что значение a должно быть членом типа T, если нет - то ошибка компиляции. То, что вы хотите, это сказать a: infer me typeof a, то есть наоборот.

Аннотации типа предназначены для ограничения значения, а не значения для ограничения типа. TS позволяет брать тип из значения, но не позволяет сразу брать тип значения и ограничивать его.


Тем не менее, мы можем сделать несколько трюков, чтобы сделать это работает. Рассмотрим решение на уровне типа:

type SpecificKeys<T extends string> = {
  [key in T]: string;
};

// type level version of makeSpecificKeys
type MakeSpecificKeys<T extends SpecificKeys<string>> = T;

const foobar = {
  foo: "foo",
  bar: "bar",
};
type FoobarType = MakeSpecificKeys<typeof foobar> // fine ?

const badfoobar = {
  foo: 1, // number value dont match SpecificKeys
  bar: "bar",
};
type BadFoobarType = MakeSpecificKeys<typeof badfoobar> // error ?

Игровая площадка

Оба значения foobar и badfoobar правильно определены TS без каких-либо аннотаций типов. Следующая вещь - это вызов уровня типа MakeSpecificKeys, который является своего рода функцией id, которую вы сделали ранее, но эта функция находится на уровне типа, она ограничивает тип аргумента так же, как это делала makeSpecificKeys. Для badfoobar это показывает ошибку компиляции.

То, что я показал здесь, несомненно, является худшим подходом, чем конструктор значений makeSpecificKeys, который вы сделали. Так что придерживайтесь этого. Единственный смысл использования вышеупомянутого подхода состоит в том, что ничего из этого не идет в среду выполнения, когда makeSpecificKeys делает.

...