microsoft / microsoft/TypeScript
Type guard should infer the type of parent object when applied on a property
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 132
Description
Suggestion
🔍 Search Terms
Type guard, parent object, infer, inference
✅ Viability Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.
⭐ Suggestion
Typescript should be able to infer the type of an object, if a type guard was checked on a property of the said object. Currently, Typescript does correctly infer the type of the property, but not its parent object.
📃 Motivating Example
The following example is very common in data oriented design.
interface Type1 { list: string[] }
interface Type2 { list: { [key: string]: string } }
declare const obj: Type1 | Type2;
if(Array.isArray(obj.list)) {
const list: string[] = obj.list; // WORKS
const map: { [key: string]: string } = obj.list; // ERROR, as expected
const objCasted: Type1 = obj; // ERROR, unexpectedly
} else {
const map: { [key: string]: string } = obj.list; // WORKS
const list: string[] = obj.list; // ERROR, as expected
const objCasted: Type2 = obj; // ERROR, unexpectedly
}
The following example works and that is good because it is an equally common case in this type of design.
interface Type3 { type: 'type3', data: boolean }
interface Type4 { type: 'type4', data: string }
declare const obj2: Type3 | Type4;
if(obj2.type === 'type3') {
const objCasted: Type3 = obj2; // WORKS
} else {
const objCasted: Type4 = obj2; // WORKS
}
So I believe the type guards should work the same way. As far as I see, this does not cause any inconsistency in the language or the type system. It is an improvement without any downsides.
💻 Use Cases
See the full example.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the two motivating examples in the linked TypeScript playground and compare the current narrowing of the property with the parent object. No source files or tests are named; done means property checks narrow the corresponding parent union in both branches without changing runtime output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100