Как бы вы назвали этот тип вывода, который TypeScript не может сделать? - PullRequest
0 голосов
/ 17 января 2019

В настоящее время в TypeScript, если для функции задано значение map, тип массива не может быть определен.

> let rfn1 = (a, fn:((x:number)=>number) ) => a.map(fn);

> .type rfn1

let rfn1: (a: any, fn: (x: number) => number) => any

Вы можете видеть, что a имеет тип any, хотя он должен иметь тип number[], чтобы предоставить действительный аргумент для функции типа ((x:number)=>number).

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

> let rfn2 = (a: number[], fn:((x:number)=>number) ) => a.map(fn);

> .type rfn2
let rfn9: (a: number[], fn: (x: number) => number) => number[]

Что бы вы назвали типом вывода, который в настоящее время здесь отсутствует, что требует явной типизации?

1 Ответ

0 голосов
/ 18 января 2019

Я вижу ваше мышление ... но это зависит от ряда недоказуемых предположений. Поэтому я бы назвал расширение типа a:

расширенный тип из-за недоказуемых предположений

Если вы работаете изнутри, у вас есть функция, которая совместима с функцией обратного вызова для array.map:

(value: number, index: number, array: number[]) => {}

Мы должны были бы предположить, что тип функции, который мы знаем о ((x: number) => number), может быть предназначен только для использования с array.map - и это первое недоказуемое предположение.

Расширяя наш взгляд на один шаг, мы имеем a.map(...). Это может быть array.map, но также может быть geoAwesome.map или буквально любым другим, где мы создали map метод. Таким образом, допущение, что a.map равно array.map, является нашим вторым недоказуемым допущением.

Даже комбинируя два предположения, мы все равно не можем доказать, что a должен быть массивом.

class NotArray {
  map(fn: (num: number) => number) {
    return fn(3);
  }
}

let rfn1 = (a, fn: ((x: number) => number)) => a.map(fn);

let res1 = rfn1([1, 2, 3], (x) => x);
console.log(res1);

let res2 = rfn1(new NotArray(), (x) => x);
console.log(res2);

Глядя на этот надуманный пример, вы можете видеть, что a может быть практически любого типа (при условии, что он имеет совместимый метод map. Следовательно, any.

Только когда мы аннотируем параметр a, компилятор может доказать, что a не относится к этим другим типам - и теперь наш пример res2 выдаст ошибку.

let rfn1 = (a: number[], fn: ((x: number) => number)) => a.map(fn);
...