Skip to content

Make "(["foo"] as const).includes()" have a less narrow parameter type #38447

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

Closed
5 tasks done
vedantroy opened this issue May 9, 2020 · 5 comments
Closed
5 tasks done
Labels
Duplicate An existing issue was already created

Comments

@vedantroy
Copy link

vedantroy commented May 9, 2020

Search Terms

"as const", "includes", "array includes"

Suggestion

Right now, the type of the first parameter (searchElement) of

const types = ["foo", "bar"] as const
const ExampleType = typeof types[number]
types.include // has very narrow type

is "foo" | "bar". However, this isn't very helpful. Because if we can only put in strings that are either "foo" or "bar" into the includes method, then there would be no point using it all (it would always return true). As such, I suggest widening the type to unknown.

What includes is helpful for is testing if an arbitrary string, "baz" is inside the array ["foo", "bar"]. If it is, then we know it belongs to ExampleType.

It would make more sense for the type of types.includes to be (rough idea):

function (searchElement: unknown, fromIndex?: number | undefined): searchElement is typeof ["foo", "bar"] as const

Use Cases

const types = ['foo', 'bar']
const ExampleType = typeof types[number]

const string: string = 'example' // some runtime value
if (types.includes(string)) {
    // string has the type ExampleType
}

Examples

Here's what happens right now

const types = ['foo', 'bar']
const ExampleType = typeof types[number]

const string: string = 'example' // some runtime value
if (types.includes(string as ExampleType)) { // have to do a cast that is logically incorrect
    // string has the type "string" and not the type "ExampleType"
}

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This doesn't change emission of JS and just makes includes more permissive and the type of example a sub-type of what it already was inside the if statement
  • This wouldn't change the runtime behavior of existing JavaScript code
  • See above
  • This could be implemented without emitting different JS based on the types of the expressions
  • See above
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • See above
  • I think?
@vedantroy vedantroy changed the title Make "(["foo"] as const).includes()" have a less narrow type Make "(["foo"] as const).includes()" have a less narrow parameter type May 9, 2020
@MartinJohns
Copy link
Contributor

Duplicate of #36352. Search terms: include union narrow

@vedantroy
Copy link
Author

vedantroy commented May 9, 2020

@MartinJohns I think my suggestion has a difference because it also suggests that if includes returns true, it should narrow the type of the input variable inside the if statement.

I read the duplicate issue link, and I now understand why allowing includes to accept any or unknown would be harmful, however, you could allow includes to only accept a narrow type and still perform the type analysis inside the if statement.

@MartinJohns
Copy link
Contributor

And that's a duplicate of #36275.

@vedantroy
Copy link
Author

@MartinJohns I see. I guess I'm confused as to why the change is complicated, it seems to be a small change in the type signature of includes (change below)? But I don't know how the Typescript compiler works, and I suspect things would get more complicated for using includes with arrays/types created with ["foo", "bar"] as const, so I won't question it.

interface Array<T> {
    includes(searchElement: T, fromIndex?: number): searchElement is T;
}

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label May 11, 2020
@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