Важно обратить внимание на то, где объявлены параметры типа c и в какой области они находятся. Тип
type FuncGenericReturn = <T>() => T;
представляет собой конкретный тип , относящийся к функции generi c . <T>() => T
означает: «функция, для которой caller указывает тип T
и которая возвращает значение типа T
». Это практически невозможно реализовать безопасно. Представьте себе, если бы у вас была такая функция:
declare const funcGenericReturn: FuncGenericReturn;
Тогда вы сможете назвать ее так:
const someNumber: number = funcGenericReturn<number>();
const someString: string = funcGenericReturn<string>();
Но, конечно, во время выполнения они оба скомпилируются в
const someNumber = funcGenericReturn();
const someString = funcGenericReturn();
Это означает, что funcGenericReturn()
просто должен "знать" во время выполнения, что он должен сначала вернуть number
, а затем string
, основываясь на информации о типе, которая стерта перед тем JavaScript генерируется. Поэтому правильная реализация FuncGenericReturn
потребует магического предузнания.
Повторюсь: если у вас есть функция generi c, параметры типа generi c задаются вызывающей стороной , не исполнителем. Это правда, что иногда компилятор выводит параметры этого типа, так что человеку, пишущему код, не нужно его прописывать, но опять же, эти выводы происходят во время вызова . Два разных вызова одной и той же функции generi c могут в конечном итоге иметь два разных выбора параметров типа.
Давайте сравним это с другим, но связанным определением типа:
type FuncConcreteReturn<T> = () => T;
Здесь FuncConcreteReturn
- это generi c тип , относящийся к конкретной функции . Точнее было бы сказать, что FuncConcreteReturn
на самом деле не тип; это больше похоже на оператор типа , который принимает тип ввода T
и производит тип вывода () => T
.
Для любого конкретного типа T
тип FuncConcreteReturn<T>
является функциональным типом concrete , который не принимает параметров и возвращает значение типа T
. Таким образом, FuncConcreteReturn<string>
- это функция, которая не принимает аргументов и возвращает string
, а FuncConcreteReturn<number>
- это функция, которая не принимает аргументов и возвращает number
. Обратите внимание, что FuncConcreteReturn<string>
отличается от FuncContreteReturn<number>
, и ни один из них не является FuncConcreteReturn
, потому что это недопустимый тип. Таким образом, действует следующее:
const funcReturnsNumber: FuncConcreteReturn<number> = () => 1;
const funcReturnsString: FuncConcreteReturn<string> = () => "";
Опять же, funcReturnsNumber
- это , а не универсальная c функция. Это конкретная функция, которая всегда возвращает число. И FuncConcreteReturn<T>
- это generi c type , где значение T
выбирается при записи типа. Так как эти типы являются типами функций, тип T
выбирается реализатором этих функций, а не вызывающей стороной .
. Кстати, связь между типом функции generi c, таким как
type G = <T, U>(t: T, u: U) => [T, U]
, и типом generi c, таким как
type H<T, U> = (t: T, u: U) => [T, U]
, заключается в том, что любой экземпляр последнего будет экземпляром из первых, но не наоборот. Это означает, что если у вас действительно есть FuncGenericReturn
, вы можете присвоить ему значение типа FuncConcreteReturn<string>
или FuncConcreteReturn<number>
:
const fn: FuncConcreteReturn<number> = funcGenericReturn; // okay
const fs: FuncConcreteReturn<string> = funcGenericReturn; // okay
или для * Типы 1098 * и H
выше, вы можете сделать это:
const g: G = <T, U>(t: T, u: U) => [t, u];
g("a", 1); // okay
g(1, "a"); // okay
const h1: H<string, number> = g; // okay
h1("a", 1); // okay
h1(1, "a"); // error
const h2: H<number, string> = g; // okay
h2(1, "a"); // okay
h2("a", 1); // error
Хорошо, я надеюсь, что это даст вам некоторое представление о разнице между функциями generi c и типами generi c , Удачи!
Детская площадка ссылка на код