Литерал шаблона как аргумент функции в Typescript

#typescript

#typescript

Вопрос:

Учитывая приведенный ниже пример:

 type AllNames = 'andre' | 'willian' | 'pedro'
type HiNames = `Hi ${AllNames}`

const value: AllNames = 'andre'

const randomFunction = (prop: HiNames) => `${prop}, how are you?`

randomFunction(`Hi ${value}`)
 

VSCode выдает следующую ошибку :
Argument of type 'string' is not assignable to parameter of type '"Hi andre" | "Hi willian" | "Hi pedro"'.

Не Hi ${value} всегда будет вычисляться Hi andre как?

Как я могу использовать литерал шаблона в качестве аргумента функции в Typescript? Любая помощь приветствуется. Спасибо.

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

1. » Разве Hi ${value} не будет всегда вычисляться как Hi andre? » Нет, с чего бы это?

2. @VLAZ Из-за const value: AllNames = 'andre' , верно?

3. Хорошо, я думал, вы имели в виду » тип HiNames = Hi ${AllNames} «`.

Ответ №1:

При вызове функции TypeScript автоматически расширяет тип выражения

 `Hi ${value}`
 

Для string .

Вы можете исправить это, используя as const для предотвращения расширения:

 randomFunction(`Hi ${value}` as const)
 

Ответ №2:

Ваш код будет работать, если вы добавите его как const .

 type AllNames = 'andre' | 'willian' | 'pedro'
type HiNames = `Hi ${AllNames}`

const value: AllNames = 'andre'

const randomFunction = (prop: HiNames) => `${prop}, how are you?`

randomFunction(`Hi ${value}` as const)

 

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

Ответ №3:

Интерпретация строки TS

Typescript позволяет объявлять типы строковых литералов на основе шаблонов, но он не интерпретирует шаблонное значение как литерал.

Рассмотрим этот простой пример:

 const a = `andre`  // type: "andre"
const b = `Hi ${a}`  // type: string
 

Typescript интерпретирует единственную строку "andre" (даже с обратными метками) как ее буквальное значение и присваивает тип a: "andre" . Затем он видит шаблон "Hi ${a}" и вставляет a: "andre" в него. Он интерпретирует эту новую переменную как b: string , хотя и шаблон, и его части являются известными литералами. Вы хотите, чтобы typescript понимал шаблон и возвращал литерал "Hi andre" , но он просто этого не делает.

Любые манипуляции со строками просто возвращаются string .

 const c = a   a; // "andreandre" - type is string
const d = a.toLowerCase(); // "andre" - not Lowercase<"andre">, just string
const e = `${a}`; // "andre" - type is string
 

Утверждение шаблонного типа

Эти типы строковых литералов являются новыми, и, возможно, это поведение изменится в будущем. Но пока, если вы хотите создать шаблонное значение, вам нужно указать его тип.

Как упоминали другие, вы можете использовать as const on для любой шаблонной строки, чтобы получить ее буквальное значение.

Вы также можете создать вспомогательную функцию, которая применяет тип шаблона при составлении строки. Здесь мы создаем утверждение внутри функции, чтобы нам не нужно было создавать утверждение при его вызове.

 const hi = <T extends string>(name: T): `Hi ${T}` => {
  return `Hi ${name}` as `Hi ${T}`;
}
 

Теперь все в порядке:

 randomFunction(hi(value));
 

Поскольку наведение курсора hi мыши на вызов функции показывает:

 const hi: <"andre">(name: "andre") => "Hi andre"
 

И полученное здесь литеральное значение "Hi andre" можно присвоить HiNames .

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