#typescript
Вопрос:
Если бы я должен был объявить тип как отдельную переменную, например:
type Foo = <T>(x: T) => T
Затем используйте его для определения функции:
const foo:Foo = x => {
let a = /*...*/
/*...function execution...*/
return a
}
Как я могу ссылаться на универсальный тип T
в теле функции, например, для объявления переменной a:T
?
Комментарии:
1. Я боюсь, что это может быть решением
const foo:Foo = <T>(x: T) => { ... }
2. Поскольку
T
это не входит в область действия определения функции, вам придется объявить это снова в определении функции, как предлагает Нишант, или в противном случае вы можете написатьtypeof x
вместоT
.
Ответ №1:
Вы никак не можете ссылаться на этот аргумент типа, потому что он находится в объявлении типа. В основном это говорит о том, что «Видите ли, любая функция, имеющая тип Foo
, является универсальной, вы можете передать аргумент типа любой функции этого типа, и ее возвращаемый тип и аргументы будут зависеть от этого аргумента типа». Этот аргумент типа T
, указанный вами Foo
, на самом деле никоим образом не существует, он просто служит для того, чтобы сообщить любому вызывающему абоненту Foo
, что он может его принять.
Теперь вы используете этот аргумент при написании фактической реализации функции типа Foo
. Нравится
type Foo = <T>(x: T) => T
const foo: Foo = <T>(x: T) => {
let a: T = x
return a
}
Или, например, вы могли бы назвать его по-другому
type Foo = <T>(x: T) => T
const foo: Foo = <U>(x: U) => {
let a: U = x
return a
}
Foo
Тип ничего не навязывает, он просто говорит: «У этой функции есть 1 аргумент типа», и функция может вызывать и использовать этот аргумент, как ей заблагорассудится. Вы даже можете полностью игнорировать это
type Foo = <T>(x: T) => T
const foo: Foo = () => {
return 5 as any
}
Опять же, что касается вызывающей функции, foo
она принимает один аргумент типа только потому foo
, что является реализацией Foo
типа, даже если foo
на самом деле не использует его.
Или вы можете добавить дополнительный аргумент типа, который является необязательным, и необязательную переменную этого типа
type Foo = <T>(x: T) => T
const foo: Foo = <U, K = number>(x: U, y?: K) => {
if(y) console.log(y)
let a: U = x
return a
}
И это все еще справедливо, потому что любой, кто звонит foo
, может посмотреть на определение типа и увидеть «Ок, Foo
принимает 1 аргумент типа и 1 обычный аргумент». Если теперь они предоставляют 1 аргумент типа и 1 аргумент обычного типа, он все равно будет работать, потому foo
что в таких условиях он работает нормально.
Ответ №2:
Просто назначьте/скопируйте/клонируйте x
a
:
type Foo = <T>(x: T) => T
const foo: Foo = x => {
let a = x
/*...function execution...*/
return a
}
Я пытался вывести универсальный тип:
type Foo = <T>(x: T) => T
type ObtainGeneric<T extends (...args: any[]) => any> = T extends (u: infer U) => infer U1 ? U amp; U1 : never
const foo: Foo = x => {
let a: ObtainGeneric<Foo> = null as ObtainGeneric<Foo>
/*...function execution...*/
return a
}
const result = foo(32)
Но безуспешно, потому что TS выводит T
как unknown
«потому T
что», будет известно, что вывод можно сделать только тогда, когда smbd вызывает функцию
Я не думаю, что это возможно/безопасно сделать в области типов.
Комментарии:
1. Как это может помочь? Вопрос в том, чтобы ссылаться
T
неx
на что .2. @Clashsoft Поскольку
x
имеет типT
, переменнаяa
также будет иметь типT
в этом коде. Вопрос в том , как объявить переменную типаT
, что и делает этот код, поэтому он отвечает на вопрос.3.
How can I reference generic type T in the function body, such as to declare variable a:T ?
— вторая часть предложения кажется мне примером. Другие люди могут наткнуться на этот вопрос с намерением сделать больше, чем просто объявить переменную с тем же типом, поэтому ответ не должен быть просто сосредоточен на примере, приведенном OP.4. Вот почему ОП может просто проигнорировать мой ответ или понизить его