Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto Type narrowing for array union type when the first element type is determined #49185

Closed
5 tasks done
maple5233 opened this issue May 20, 2022 · 2 comments
Closed
5 tasks done
Labels
Duplicate An existing issue was already created

Comments

@maple5233
Copy link

maple5233 commented May 20, 2022

Suggestion

πŸ” Search Terms

is:issue union type array guard first element

βœ… 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

If we have a union type array like declare const array: string[] | number[], and the first element type is determined in a branch, we should be able to narrow the array type to string[] or number[].
(Of course we can now use custom type guards for our purposes, but it would be exciting if this were all automated.)

πŸ“ƒ Motivating Example

playground

// ts version: 4.6.4

// case 1
declare const array: string[] | number[]
function doSomething() {
  if (typeof array[0] === 'string') {
      const firstElement = array[0] // When the mouse hovers over the variable, you can see that the ts engine correctly infers the type, which is 'string'
      type firstElementType = typeof array[0] // should be 'string' (currently it is 'string | number')
      type arrayType = typeof array // should be 'string[]' (currently it is 'string[] | number[]')
  }
}

// case 2
interface A { foo: number }
interface B { bar: number }
declare const array2: A[] | B[]
function doSomething2() {
  if ('foo' in array2[0]) {
    const firstElement = array2[0] // When the mouse hovers over the variable, you can see that the ts engine correctly infers the type, which is 'A'
    type firstElementType = typeof array2[0] // should be 'A' (currently it is 'A | B')
    type arrayType = typeof array2 // should be 'A[]' (currently it is 'A[] | B[]')
  }
}

// No longer need to write a custom type guard as a helper function like this:
function boringButNeededHelperGuard(array: string[] | number[]): array is string[] {
  return typeof array[0] === 'string'
}

πŸ’» Use Cases

Save time writing custom type guards, and code reading experience will be better

@MartinJohns
Copy link
Contributor

This sounds like a duplicate of #45301 to me, which was marked as a duplicate of #42384.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label May 20, 2022
@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants