我遇到打字麻烦:
function identity<T>(v: T): T{ return v; }
function execute(fn: {(n: number):string}) {}
execute((n) => {
// type of n is 'number'
return n.toFixed();
})
execute(identity((n) => {
// type of n is 'any'
return n.toFixed();
}))
当键入的高阶函数execute
接收到一个函数时,该匿名函数的参数将通过推断来键入。但是,将该匿名函数传递给包装器identity
会导致这些推断的类型丢失。我可以对execute
或identity
的结构进行任何调整,以允许仍推断出这些类型吗?
注意为简单起见,identity
在这里是一个纯函数。实际上,它不是,但是应该具有与此identity
函数相同的类型。有关问题的更多信息,请参见checkpoint
。
上下文
这是我在React组件生命周期的上下文中加载数据时遇到的问题的一般形式。因为不应该在不再安装的组件上调用setState
,所以可以防止触发加载回调。
function loadData():Promise<MyDataType> {/*...*/}
// Wraps the passed function (handleDataLoaded),
// such that when the returned function is executed the
// passed function is conditionally executed depending
// on closure state.
function checkpoint(fn){/*...*/}
// Add data to the state of the component
function handleDataLoaded(val: MyDataType){/*...*/}
// react lifecycle hook componentDidMount
loadData()
.then(checkpoint(handleDataLoaded));
// react lifecycle hook componentWillUnmount
// adjusts state of checkpoint's closure such that handleDataloaded
// is not fired after componentWillUnmount
答案 0 :(得分:1)
您写的实际上与以下内容相同:
function identity<T>(v: T): T{ return v; }
function execute(fn: {(n: number):string}) {}
execute((n) => {
// type of n is 'number'
return n.toFixed();
})
var func = identity((n) => {
// type of n is 'any'
return n.toFixed();
});
execute(func);
否,当您明确提供通用参数时:
var func = identity<number>((n) => {
// type of n is 'any'
return n.toFixed();
});
您将收到编译器错误:
现在,您看到的是传递的是函数而不是数字。
如果您解释您要做什么,我们也许可以为您提供解决方案。
答案 1 :(得分:1)
绝对没有麻烦。这更像是您在逻辑上遇到了一些错误(在您的脑海中)。不使用严格模式是另一个问题。
/* execute( */ identity((n) => {
// type of n is 'any', why wouldn't it be?
// There is no type constraint in `identity` function,
// hence you have absolutely no reason to expect `n` to have type `number`
// I commented out the wrapping by `execute` function
// so that it doesn't confuse you. Because, no matter
// if it's there or not, you should first figure out
// the shape and type of underlying expression,
// because this is how Typescript figures them out.
return n.toFixed();
}) /* ) */
但是
function identity<T extends {(n: number): string}>(v: T): T{ return v; }
/* execute( */ identity((n) => {
// type of n is 'number', because we added a constraint to the type parameter `T` in `identity` function
return n.toFixed();
}) /* ) */
您也可以这样做:
/* execute( */ identity<{(n: number): string}>((n) => {
// type of n is 'number'
return n.toFixed();
}) /* ) */
和
execute(identity((n: string) => {
// this is a TS error
// "Argument of type '(n: string) => () => string' is not
// assignable to parameter of type '(n: number) => string'"
return n.toFixed;
}))
最后,您应该始终使用严格模式(将"strict": true
添加到tsconfig.json的“ compilerOptions”中),您将永远不会遇到此类警告。