#typescript
#typescript
Вопрос:
У меня есть функция
function foo() {
return ["", 1, () => ""];
}
типы: string
, number
и (() => string)
однако после того, как я разрушу эти значения
const [str, num, func] = foo();
компилятор обрабатывает каждую переменную как тип: string | number | (() => string)
Я хочу передать эти переменные в функции, но компилятор жалуется, что типы не совпадают, и моя среда разработки сходит с ума из-за красного текста. Что я могу сделать?
Ответ №1:
Укажите тип возвращаемого значения функции
function foo(): [string, number, () => string] {
return ["", 1, () => ""];
}
Это будет строго вводить функцию для возврата массива с:
- значение индекса 0 должно быть типом
string
- значение индекса 1 должно быть типом
number
- значение индекса 2 должно быть типом
() => string
/ функцией, возвращающей строку
function foo(): [string, number, () => string] {
return [0, 1, () => ""]; // Will shows error because index 0 is number, not string
}
Комментарии:
1. Это было просто. Спасибо 🙂
2. Я предполагаю, что это потому, что TS выводит возвращаемый тип из массива
any
? илиunknown
? Как TS выводит типы в этой ситуации?3. Когда вы возвращаете массив из функции, Typescript автоматически устанавливает возвращаемый тип как все возможные типы внутри возвращаемого массива, вот почему @MatasLiu получает
string | number | (() => string)
для каждого типа возвращаемого значения массива, как описано в ответе @Curtis Fenner, а неany
илиunknown
. Если вы хотите строго ввести его как"index 0 is string, index 1 is number, index 2 is function"
, вам нужно объявить возвращаемый тип, как я сделал в своем ответе.4. Я бы предположил, что ваша альтернатива небезопасна и
as
является опасной операцией, было бы хорошо, если бы вы удалили альтернативу 😉
Ответ №2:
По умолчанию TypeScript определяет тип литерала массива не как кортеж, а как массив объединения всех типов элементов. Таким образом, const x = [a, b, c];
предполагается, что in не имеет типа [A, B, C]
, а вместо этого (A | B | C)[]
.
Если вы хотите, чтобы TypeScript определял тип кортежа, вы должны явно указать, что:
const x: [A, B, C] = [a, b, c]; // this typechecks
Альтернативой является использование as const
синтаксиса:
const x = [a, b, c] as const; // infers as `readonly [A, B, C]`
Это не единственное место, где TypeScript выводит менее специфичный тип, чем кажется возможным. Например, строковые литералы по умолчанию выводят as string
вместо их литерального типа: let x = "word"; // string
vs let x = "word" as const; // "word"
vs const x = "word"; // "word"
Ответ №3:
Другой способ добиться этого:
function foo() {
return ['', 1, () => ''] as const
}
const [str, num, func] = foo()
Основное различие с as const
и без него заключается в том, что:
as const
сообщает ts, что это неизменяемое значение, следовательно, ts выводит конкретный тип, который в данном случае является кортежем из 3, и, как вы знаете, кортеж может иметь разные типы- без этого
as const
ts выводит это какArray
, а массив принимает параметр одного типа, но в этом случае массив содержит значения string, number и func. Следовательно, ts выводит это как(string | number | () -> string)[]
Комментарии:
1. Это определенно более элегантно!