Closed
Description
🔍 Search Terms
Introduction:
Consider the following TypeScript types:
type Ob1 = {
a: string,
b?: never
}
type Ob2 = {
a: string,
}
type Ob3 = {
a: string,
b?: number
}
type Ob4 = {
a: string,
b: number
}
type Ob5 = {
a: string,
b?: undefined
}
type Ob6 = {
a: string,
b?: unknown
}
declare let n1: Ob1
declare let n2: Ob2
declare let n3: Ob3
declare let n4: Ob4
declare let n5: Ob5
declare let n6: Ob6
// OK
let case1: Ob1 = n2
let case1_1: Ob2 = n1
// Error
let case2: Ob1 = n3
let case3: Ob1 = n4
// Error if exactOptionalPropertyTypes=true
let case4: Ob1 = n5
let case5: Ob1 = n6
Is the compatibility between types Ob1 and Ob2 part of an intended trade-off within TypeScript's type system?
Or,
✅ Viability Checklist
- 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 isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
⭐ Suggestion
Introduce stricter type checking for optional never to prevent runtime errors, such as:
const funcB = (params: { b: string }) => {
const result = funcA(params) // Type Check Error expected here
console.log("Result Length: ", result.length)
}
📃 Motivating Example
The inconsistency above can lead to unintended runtime errors. For instance:
type Params = { a?: never, b: string } | { a: string, c: string }
const funcA = (params: Params): string => {
if (params.a !== undefined) {
return params.c
} else {
return params.b
}
}
const funcB = (params: { b: string }) => {
const result = funcA(params)
console.log("Result Length: ", result.length) // runtime error
}
const params = { a: 'a', b: 'b' }
funcB(params)
The code compiles without errors but causes runtime issues.
💻 Use Cases
- What do you want to use this for?
- What shortcomings exist with current approaches?
- What workarounds are you using in the meantime?
Metadata
Metadata
Assignees
Labels
No labels