Более строгий тип возвращаемого значения для объектного литерала в Typescript

#typescript #type-inference

Вопрос:

В этом коде

 const s = "myKey" as const;
const myF = () => ({
  [s]: 0,
});
 

тип myF является function myF(): {[p: string]: number, myKey: number}

где тип возвращаемого значения {[p: string]: number, myKey: number}

Как вы можете видеть, [p: string]: number здесь нежелательные утечки.

Как сделать тип возвращаемого значения ожидаемым {MyKey: число} без явной аннотации типа?

Я пока не хочу вдаваться в явные аннотации, так как у меня есть несколько типов с большим количеством полей.

Комментарии:

1. Какую версию машинописного текста вы используете? Когда я вставляю ваш код на игровую площадку typescript , я вижу myF () => { myKey: number } , что для большинства версий typescript есть тип

2. Является ли ваш фактический код более сложным, чем описанный выше? Я бы предположил, что у вас может возникнуть ситуация, когда эквивалент s в вашем реальном коде вводится как string , а не как определенный тип строкового литерала и вызывает то, что вы видите.

3. Игровая площадка Typescript показывает ожидаемое поведение. Возможно, проблема в том, что я проверяю инспектора типов IDEA (Ultimate / Webstorm, не имеет значения). Может быть, это действительно проблема с ИДЕЕЙ.

4. > является ли ваш фактический код более сложным, чем описанный выше? Это так, но я упростил его в этом примере.

Ответ №1:

Это поведение TypeScript по умолчанию. Он всегда оценивает вычисляемое свойство в строку.

Вы можете написать пользовательский помощник для создания объектов:

 const s = "myKey";

const record = <Prop extends PropertyKey, Value>(prop: Prop, value: Value) => 
  ({ [prop]: value }) as Record<Prop, Value>

// const myF: () => Record<"myKey", number>
const myF = () => record(s, 42)
 

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

Вам не нужно использовать as const

Имейте в виду, что у этого решения есть недостаток.

 const drawback = record<'myKey' amp; { hello?: 'world' }, 42>('myKey', 42).myKey // error
 

Следовательно, вам лучше избегать использования явных обобщений для этой функции

Комментарии:

1. > Это поведение TypeScript по умолчанию. Он всегда оценивает вычисляемое свойство в строку. « const prop = «PROP»; const myO = { [prop]: 1 }; « будет иметь тип {PROP: number}

2. Я думаю, что это то, чего я пытаюсь достичь — иметь такое же поведение с возвращением функции. Мой настоящий тип немного больше, чем это — у него есть несколько реквизитов с разными типами.

3. @IgorLoskutov пожалуйста, поделитесь своим реальным примером