Microsoft/TypeScript
GitHub ã§èŠã`keyof T['prop']` becomes never when the object contains a context-sensitive function
Open
#55,039 opened on 2023幎7æ17æ¥
BugDomain: Indexed Access TypesHelp Wanted
Repository metrics
- Stars
- Â (48,455 stars)
- PR merge metrics
-  (å¹³åããŒãž 6d 17h) (30d ã§ 9 merged PRs)
説æ
Bug Report
ð Search Terms
Not sure how to put this but:
- recursive type
- function
- parameter
- generics
ð Version & Regression Information
Tested on these versions:
- typescript@5.1.3
- typescript@5.2.0-dev.20230716 dev
⯠Playground Link
Code
type Type<
TAcceptedKeys extends string,
TType extends Type<TAcceptedKeys>=any
> = {
/**
* We're using the keys of this property, that is why
* we use a recursive type.
*/
obj?: Record<TAcceptedKeys, 1>
/**
* Just for the sake of illustration.
* In the circumstances of the bug this will be never[].
*/
keys: (keyof TType['obj'])[]
/**
* A function with a parameter inside the recursive type.
* This triggers the bug.
*/
triggerFn?: (param: number) => void
/**
* This will always be TType, regardless of whether
* a parameter is declared in `triggerFn` or not.
*/
shouldBeTType?: TType
/**
* This will be `keyof TType` as expected if a parameter
* is not declared in triggerFn, but it will turn to `undefined`
* as soon as a parameter is declared in that function.
*
* If the below property is passed to defineType
* the type will be as expected:
* triggerFn: () => {}
*
* However this will trigger the bug:
* triggerFn: (param) => {}
*/
shouldBeKeyofTType?: keyof TType
}
const defineType = <TAcceptedKeys extends string>() =>
<const TType extends Type<TAcceptedKeys, TType>>(type: TType) => type
defineType<'apple' | 'banana'>()({
obj: {
apple: 1,
banana: 1
},
keys: [
'apple'
],
/**
* Toggle these comments to see how the bug works.
*/
triggerFn: () => {}, // won't produce diagnostics
// triggerFn: (param) => {}, // type 'string' is not assignable to type 'never'
/**
* Toggle these comments to see diagnostics information.
*/
// shouldBeTType: null,
// shouldBeKeyofTType: null
})
ð Actual behavior
The presence or absence of a parameter in an object member function has effect on this object type in certain circumstances.
ð Expected behavior
It shouldn't.