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

Using startsWith & endsWith to narrow type #46958

Closed
LinusU opened this issue Nov 30, 2021 · 3 comments
Closed

Using startsWith & endsWith to narrow type #46958

LinusU opened this issue Nov 30, 2021 · 3 comments
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript

Comments

@LinusU
Copy link
Contributor

LinusU commented Nov 30, 2021

lib Update Request

Configuration Check

My compilation target is ES2020 and my lib is ES2020.

Missing / Incorrect Definition

startsWith & endsWith doesn't narrow the the type, it just returns a boolean.

Sample Code

interface BuiltinPaymentMethod {
  id: `builtin-${string}`
  // ...
}

// ...

declare const id: string

if (id.startsWith('builtin-')) {
  // Here I want `id` to be typed as `builtin-${string}`
}

Documentation Link

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith

Pull Request

#46959 🚀

@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Nov 30, 2021

I don't think this is a good fit for the general library. Two main concerns: Changing a function from not-overloaded to overloaded has fairly pervasive effects in areas like contextual typing, generic inference, and how exactly it can be invoked when the method operand is a union. The other is that template string literals are inherently combinatorially explosive, so a call like startsWith(union of 24) && endsWith(union of 24) produces a union of 576 elements, which is bad from a performance and comprehensibility perspective.

Thankfully since this is an additional overload rather than a replacement, you can add it to your own project through declaration merging if those trade-offs are a good fit for your use cases.

@RyanCavanaugh RyanCavanaugh added Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript labels Nov 30, 2021
@LinusU
Copy link
Contributor Author

LinusU commented Dec 1, 2021

Fair enough, thanks for taking the time to explain

@alexgleason
Copy link

Here is a declaration that does it:

interface String {
  startsWith<P extends string>(searchString: P): this is `${P}${string}`;
  startsWith<P extends string>(searchString: P, position: 0): this is `${P}${string}`;
}

I created an MR to add this to the ts-reset package: total-typescript/ts-reset#161

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants