在恒等函数中使用return关键字或使用可选参数时的错误推断



我在使用身份函数时遇到了非常奇怪的行为。我正在写一个向导系统与模式(附件是一个操场链接与一个非常简化的版本),并使用约束身份函数来获得推理。

当我使用以下任何一个属性时,问题发生在一个无法推断的属性中:

  • 当标识函数返回的值使用return关键字时(而不是用圆括号包装的单行返回值)。或
  • 在恒等函数中声明可选参数时。参数在恒等函数的类型定义中声明,当使用Parameters<typeof myFunction>时,无论声明参数还是不声明参数,都可以正确地推断。

这两个问题对我来说都是超级奇怪的,这意味着我要么错过了一些非常基本的东西,要么我发现了两个罕见的错误。

这在所有可用的playground版本(尝试到3.3.3)中都会重现,在4.8中也会重现。

游乐场链接及相关代码

最好检查一下代码示例,但是这里:

此话类型:

type Schema = Record<string, unknown> // modified from original for the sake of the example, if it doesn't make sense
type StepFunction<
TSchema extends Schema = Schema,
> = (anything: unknown) => {
readonly schema: TSchema
readonly toAnswers?: (keys: keyof TSchema) => unknown
}
function step<TSchema extends Schema = Schema>(
stepVal: StepFunction<TSchema>,
): StepFunction<TSchema> {
return stepVal
}

例子:注意,所有函数的返回对象都是相同的!不同之处在于:

  • 是否使用return关键字(?!?!)
  • 是否有step函数的参数。并不是说,如果我做Parameters<typeof myStepValue>即使参数丢失,它被正确推断(!)
// WORKS: `keys` is inferred based on the `schema`
// - no argument for `step` function
// - no `return` keyword
const workingExample = step(() => ({
schema: {
attribute: 'anything',
},
toAnswers: keys => {
// RESULT: `keys` inferred successfully as `attribute`
type Test = string extends typeof keys ? never : 'true'
const test: Test = 'true'
return { test }
},
}))
// FAILS: `keys` is not inferred based on the `schema`
// - has argument for `step` function
const nonWorkingA = step(_something => ({
schema: {
attribute: 'anything',
},
toAnswers: keys => {
// RESULT: `keys` failed to inferred hence defaults to `string`
type Test = string extends typeof keys ? never : 'true'
const test: Test = 'true'
return { test }
},
}))
// FAILS: `keys` is not inferred based on the `schema`
// - has `return` keyword rather than a "single-return" return with parentheses
const nonWorkingB = step(() => {
return {
schema: {
attribute: 'anything',
},
toAnswers: keys => {
// RESULT: `keys` failed to inferred hence defaults to `string`
type Test = string extends typeof keys ? never : 'true'
const test: Test = 'true'
return { test }
},
}
})

你可以简化你的字体:

type Step<TSchema> = (store: TSchema) => {
data: {
schema: TSchema
toAnswers?: (keys: keyof TSchema) => unknown
}
}
function step<TSchema extends Schema>(x: Step<TSchema>) {
return x
}

我认为有两个原因:

  • nonWorkingA中有两个事实来源-一个来自参数,一个来自内部对象结构(参数_store隐式具有any类型),如果你指定_store的类型,它应该工作
  • nonWorkingB你使用statements(返回)代替expressions和typescript不能推断类型

我已经在这上面工作了将近3个小时,但仍然无法弄清楚如何进行正常的类型推断

显然这是一个关于上下文敏感表达式的TypeScript推断问题(参见https://github.com/microsoft/TypeScript/issues/49951和https://github.com/microsoft/TypeScript/issues/47599)。

然而,我确实找到了一个临时解决方案-通过用恒等函数包装返回值,边缘情况可以工作。

例如:

step(_something => (identityOfStep({
schema: {
attribute: 'anything',
},
toAnswers: keys => {
// RESULT: `keys` failed to inferred hence defaults to `string`
type Test = string extends typeof keys ? never : 'true'
const test: Test = 'true'
return { test }
},
})))

操场示例

相关内容

  • 没有找到相关文章

最新更新