TypeScript: Incorrect inference when using an optional argument
π Search Terms
Inference, Return, Arguments, Parentheses, Identity Function.
π Version & Regression Information
This reproduces in all available playground versions (tried down to 3.3.3), and also in 5.3.3.
β― Playground Link
π» Code
This is a followup on https://github.com/microsoft/TypeScript/issues/49951 which @Andarist asked me to open a follow-up issue. Also relates to https://github.com/microsoft/TypeScript/issues/47599
Probably better to check the playground for code examples, but hereβs the TL;DR:
TYPES DECLERATIONS:
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
}
EXAMPLES:
Notice the returned object of all functions is the same! The difference is in whether we have the argument for the step function or not. Note that if I do Parameters<typeof myStepValue> even when the argument is missing, itβs inferred correctly (!)
// 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 be inferred hence defaults to `string`
type Test = string extends typeof keys ? never : 'true'
const test: Test = 'true'
return { test }
},
}))
π Actual behavior
Nested valueβs function argument cannot be inferred correctly.
If I change the property (toAnswers) from a function to a simple property, there are no inference issues.
π Expected behavior
Nested value function argument should be inferred correctly regardless of the return keyword or declaring the arguments.
Additional information about the issue
Like mentioned above, this is a followup on https://github.com/microsoft/TypeScript/issues/49951 and https://github.com/microsoft/TypeScript/issues/47599
About this issue
- Original URL
- State: closed
- Created 6 months ago
- Comments: 17 (8 by maintainers)
It has been marked as a duplicate of that umbrella issue - and many issues were linked to it as its duplicates. I think this one was nice since it focused on a more specific problem. I still think this one is fixable (I fixed it locally without breaking any test cases). It was a busy weekend for me though and Iβm investigating a better fix than what I have so far. Iβll report back when Iβm done but it might take some days. TLDR: I still plan to open a PR fixing this π
Ah, ok - then the snipper in https://github.com/microsoft/TypeScript/issues/57021#issuecomment-1888949418 doesnβt exactly show the real usage. Thanks for the explanation.
If those are two different schemas then ye, it might work.
I have some idea how this might get fixed. Stay tuned π I wonder though - whatβs
anythingin your real code? Is it really meant to always beunknown?