[英]How to fix generic TypeScript function to return valid inferred type?
[英]TypeScript generic function with inferred return type
如何键入具有通用参数的 function,然后可以返回任何类型,并从用法中推断出 function 的返回类型?
我试过这个:
type Thing<T> = <U>(value: T) => U
const shouldMakeStrings: Thing<string> = (a: string) => a + 'foo'
const shouldMakeObjects: Thing<string> = (a: string) => ({ foo: a })
我的期望是shouldMakeStrings
的类型是(a: string) => string
而shouldMakeObjects
的类型是(a: string) => { foo: string }
相反,它们会出错,因为'U' could be instantiated with an arbitrary type which could be unrelated to 'string'
如何在不定义 U 的情况下定义Thing
类型,同时告诉它我想要允许任何返回类型?
这是我正在尝试做的更完整的示例( 游乐场链接):
type Thing<T> = <U>(value: T) => U
// Example, this will be a big map of custom types and string representations
type Types = {
'string': string,
'number': number
}
type CallbackMap = {
[P in keyof Types]?: Thing<Types[P]>
}
const callbacks: CallbackMap = {}
const addCallback = <V>(type: keyof Types, callback: Thing<V>) => {
callbacks[type] = callback
}
addCallback('string', (a: string) => a + 'foo')
addCallback('number', (a: number) => { foo: a })
callbacks.string // = callback that takes a string and returns something, with it's type inferred as string from `addCallback('string')` above
callbacks.number // = callback that takes a number and returns something, with it's type inferred as '{ foo: number }' from `addCallback('number')` above
这是一个更详细的示例,但它还有其他 TypeScript 问题( 操场):
type A = { foo: string }
type B = { bar: string }
type C = number[]
type Modifiable = {
'typeA': A,
'typeB': B,
'typeC': C
}
type Modifier<T> = <U>(value: T) => U
type ModifierMap = {
[P in keyof Modifiable]?: Modifier<Modifiable[P]>
}
const modifiers: ModifierMap = {
'typeA': (a: A) => a
}
const setModifier = <V extends keyof Modifiable = keyof Modifiable>(type: V, callback: Modifier<Modifiable[V]>) => {
modifiers[type] = callback
}
setModifier('typeA', (input: A) => input.foo + 'a')
setModifier('typeA', a => a.foo)
// With the aim to be able to do something like this:
const makeModifiedA = (modifiers?: ModifierMap) => {
const a = { foo: "hello world" }
return modifiers?.typeA ? modifiers.typeA(a) : a
}
makeModifiedA(modifiers) // = "hello world"
setModifier('typeA', (input: A) => ({ ...input, upperFoo: input.foo.toUpperCase() }))
makeModifiedA(modifiers) // = { foo: "hello world", upperFoo: "HELLO WORLD" }
any
/ unknown
都会匹配吗?
type Thing<T> = (value: T) => unknown
const shouldMakeStrings: Thing<string> = (a: string) => a + 'foo'
const shouldMakeObjects: Thing<string> = (a: string) => ({ foo: a })
在 TypeScript 中,您可以分配类型或推断类型。 你不能两者兼得。
您可以做的一件事是编写 hack 来检查 function 是否“满足”约束而不“擦除”其类型。 然后仍会推断其类型,但首先会对其进行约束检查。
const satisfies = <Constraint>() => <Input extends Constraint>(input: Input) => input;
const checked = satisfies<(arg: string) => any>()(arg1 => {
console.log(arg1);
return 2;
});
实际上有一个相关的提案正在进行中,很快就会将其添加为语言功能, satisfies
运算符。
https://github.com/microsoft/TypeScript/issues/47920
所以在未来的 TS 4.9+ 你会写这样的东西:
const checked = ((arg1: string) => 2) satisfies (arg: string) => any
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.