Итак, скажем, у меня есть
declare function doSomething(...args: any[]): any
interface Example {
a: number
b: number
}
doSomething({a: 2, b: 1, c: 10} as Example)
Это не сообщает об ошибке, поскольку этот объект расширяет Example
, и typescript доволен, поэтому я использую уродливую функцию идентификации:
function cast<T>(arg: T) {
return arg
}
doSomething(cast<Example>({a: 2, b: 1, c: 10})) // yay, error
Меня чертовски раздражает, что мне нужно на самом деле вызвать функцию %^#% no-op только для того, чтобы выполнить правильное приведение типа. Я заканчиваю тем, что объявляю его в каждом файле, который в нем нуждается, просто чтобы дать компилятору js больше шансов его оптимизировать.
Есть ли какая-то магия ts, о которой я не знаю, которая может избежать вызова функции?
И да, я знаю, что могу сделать это:
const x: Example = {a: 2, b: 1, c: 10}
doSomething(x)
и это:
declare function doSomething(arg: Example): any
тут действительно не в этом дело. Рассмотрим следующую лямбду:
const example = (i: number, j: number, k: number) => cast<Example>({a: 1, b: 2, c: 3})
чтобы правильно установить тип, не приводя к функции идентификации, мне нужно было бы написать
const example: (i: number, j: number, k: number) => Example = (i, j, k) => ({a: 1, b: 2, c: 3})
который не очень СУХОЙ
И да, я могу просто написать
function example (i: number, j: number, k: number): Example {
return {a: 1, b: 2, c: 3}
}
опять же не суть
// редактировать
поскольку @thedude просто поразил меня в комментарии синтаксисом ввода лямбда-возврата, о котором я не знал, еще один пример, где я использую это приведение
declare function doSomethingWithArray(arg: Example[]): void
doSomethingWithArray(cast<(Example | boolean)[]>([
{a: 1, b: 2},
false,
{a: 1, b: 2, c: 3}
]).filter(x => x) as Example[])
// редактируем 2
как кажется, я плохо объясняю, что я хочу, другой пример: эта общая функция решает проблему примера фильтра
function filterFalse<T>(x: (T | false)[]) {
return x.filter(x => x) as Exclude<T, false>[]
}
doSomethingWithArray(filterFalse<Example>([
{a: 1, b: 2},
false,
{a: 1, b: 2, c: 3} // error
]))
но требует определения специализированной функции только для этой конкретной задачи. Я спрашиваю, есть ли общий способ принудительной проверки строгого типа для литерала времени компиляции без вызова функции. Итак, именно то, что делает cast<T>
, но без бессмысленного вызова в выводе js.
const example = (i: number, j: number, k: number): Example => ({a: 1, b: 2, c: 3})
- person thedude   schedule 11.07.2021any
, то вам очень редко нужно выполнять подобное приведение типов. - person Alex Wayne   schedule 12.07.2021cast
. Функцияfilter
может работать с любым массивом, поэтому вы можете передать ей массив смешанных логических значений иExample
объектов. Typescript уже сделает вывод, что тип этого массива —(boolean | Example)[]
. - person siride   schedule 12.07.2021doSomethingWithArray([{a: 1, b: 2, c: 3}].filter(x => x))
не выходит из строя наc
, а без фильтра выходит. - person Otis Vallone   schedule 12.07.2021as (boolean | Example)[]
в массиве перед вызовом фильтра. Вам никогда не нужна функцияcast
. Вам просто нужно использоватьas
или следовать этому коду, чтобы сообщить TypeScript, чтоfilter
является защитой типа: stackoverflow.com/questions/43010737/. - person siride   schedule 12.07.2021c
, не существующую вExample
, пожалуйста, покажите мне, как это сделать, я не понимаю, как этого добиться ни с утверждениями типа, ни с защитой типа, ни без определения специализированной функции только для это - person Otis Vallone   schedule 12.07.2021filter()
может принимать массив чего угодно, в принципе. Прежде чем вы приступите к фильтрации, вы должны убедиться, что массив уже ограничен. See this example: typescriptlang.org/play?#code/. - person siride   schedule 13.07.2021