Создание объекта на основе типов typescript

0

Вопрос

Чтобы не сказать, что у меня есть такой тип

type foo = {
 go: string;
 start: string;
}

Как я могу динамически создать функцию, которая будет возвращать

{ go: '', start: '' }

Есть ли какой-либо способ в скрипте типа динамически генерировать пустой объект на основе только типа? Или это невозможно, потому что мы не можем просто зацикливаться

Я думал о чем-то вроде этого

function generate<T>(T)<T>  {
 const obj = {}
 for (const key of keyof T) {
   obj[key] = ''
 }
 return obj
}
typescript
2021-11-23 19:36:25
2

Лучший ответ

2

При запуске компилятора TypeScript (tsc) для переноса кода машинописного текста в выполняемый JavaScript стирается система статических типов языка. Так что ваш Foo тип (переименованный в верхний регистр в соответствии с соглашениями об именовании TS) не присутствует ни в какой форме во время выполнения. Нет ничего, что вы могли бы повторить, чтобы получить ключи go и start.


Самый простой способ добиться того, чтобы что-то произошло во время выполнения, - это написать JavaScript, необходимый для этого, а затем убедиться, что компилятор TypeScript может предоставить вам сильные типы, которые вам нужны, пока вы его пишете. Это в основном обратная сторона того, что вы пытаетесь сделать.

В вашем случае: что делает generate() нужно для того, чтобы работать во время выполнения? Хорошо, если мы можем предположить, что значения, генерируемые generate() будут объекты, содержащие только string-значение свойства, то нам нужно передать ему список ключей объекта. Ну и что, если мы напишем generate() для этого, а затем определите Foo с точки зрения выпуска generate() а не наоборот?

Например:

function generate<K extends PropertyKey>(...keys: K[]) {
  return Object.fromEntries(keys.map(k => [k, ""])) as { [P in K]: string };
}

const myFooObject = generate("go", "start");

type Foo = typeof myFooObject;
/* type Foo = {
    go: string;
    start: string;
} */

console.log(myFooObject)
/* {
  "go": "",
  "start": ""
} */

Здесь generate() является универсальной функцией, которая принимает список ключей (типа K) и выдает значение типа с ключами в K и значения типа string. Что {[P in K]: string} является ли сопоставленный тип эквивалентным Record<K, string> используя Record<K, V> тип полезности.

Реализация используетObject.fromEntries() для создания объекта, и тип возвращаемого значения утверждается как правильный тип, потому что TypeScript видит Object.fromEntries() как возвращающий тип, который слишком широк для наших целей.

В любом случае, когда ты позвонишь const myFooObject = generate("go", "start"), он создает значение типа {go: string; start: string}, что совпадает с вашим Foo Тип. Поэтому мы можем просто определить Foo как type Foo = typeof myFooObject вместо того, чтобы делать это вручную. Вы все еще можете сделать это вручную, но суть, которую я здесь показываю, заключается в том, что гораздо проще писать СУХОЙ код в TypeScript, если вы начнете со значений и создадите типы из них, вместо того, чтобы пытаться сделать это наоборот.


Опять же, если вы используете компилятор TypeScript tsc как есть, затем стирание типа не позволяет вам писать generate() из определения понятия Foo. Но...

Если вы хотите добавить этап сборки в свой проект и выполнить генерацию кода с помощью API компилятора TypeScript или что-то в этом роде, вы можете выполнять произвольные действия с типами. Существуют библиотеки, которые делают то же, что и вы; например, ts-auto-mock утверждает, что создает фиктивные объекты с заданным типом объекта, который в точности соответствует вашему варианту использования.

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

Ссылка на игровую площадку для кода

2021-11-25 04:07:53
1

Вы могли бы сделать его универсальным, вот так:

type foo<T extends string = string> = {
    go: T;
    start: T;
}

const test: foo<''> = {
    go: '',
    start: '',
};

Игровая площадка для машинописи

2021-11-23 19:47:19

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................

Популярное в этой категории

Популярные вопросы в этой категории