Ответ - нет. Тип ограничивает значение, говоря, 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
делает.