Typescript передает переменную в качестве параметра универсального типа

#typescript #typescript-typings #typescript-generics

#typescript #typescript-typings #typescript-generics

Вопрос:

У меня есть функция, которая принимает строку или массив строк и возвращает объект с ключами этой строки.

Вот фиктивная функция:

 type myType<T extends string> = { [K in T]: string }
const myFunc = <T extends string>(param: T | T[]): myType<T> => {
    let result = <myType<T>>{}
    // some codes here...
    return resu<
}
 

С помощью приведенного выше кода я уже добился этого:

 let val = myFunc(['foo', 'bar']);
val.foo // valid
val.other // invalid
 

Но если я передам переменную в функцию, все строковые ключи будут действительными:

 let variable = ['foo', 'bar'];
let val = myFunc(variable);
val.foo // valid
val.other // valid
 

Есть ли обходной путь, чтобы я мог передать переменную, но все еще работал так, как я ожидал?

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

1. Я думаю, вам нужно что-то вроде string extends T ? never : , но я не знаю, какой синтаксис для этого

Ответ №1:

Когда вы создаете переменную let variable = ['foo', 'bar'] , тип variable становится string[] , и вы теряете информацию о конкретных строках в массиве. Вам нужно использовать as const , чтобы Typescript интерпретировал variable как фиксированный кортеж строковых литералов 'foo' и 'bar' . Поскольку этот фиксированный кортеж является readonly , вам также необходимо изменить свою функцию, чтобы принимать readonly массивы.

 const myFunc = <T extends string>(param: T | readonly T[]): myType<T> => {
 
 let variable = ['foo', 'bar'] as const;
let val2 = myFunc(variable);
val2.foo // valid
val2.other // invalid
 

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

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

1. Есть ли способ не использовать as const ? Его легко забыть добавить, и ошибка не выдается.

2. Ну, вы можете передать ее непосредственно в функцию, но вы уже сказали, что не хотите этого делать. Вы можете назначить явный тип let variable: ['foo', 'bar'] = ['foo', 'bar'] .