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

Support inferring type guards #57260

Closed
6 tasks done
erik-kallen opened this issue Feb 1, 2024 · 2 comments
Closed
6 tasks done

Support inferring type guards #57260

erik-kallen opened this issue Feb 1, 2024 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@erik-kallen
Copy link

πŸ” Search Terms

type guard infer

βœ… Viability Checklist

⭐ Suggestion

Add the ability to infer type guard function return types.

πŸ“ƒ Motivating Example

Typescript today supports type guards of the format function isString(s: unknown) : s is string). Today we need to manually specify which type the guard checks for, but the compiler should be able to infer this from narrowing.

For example (using hypothetical syntax):

const isString = (s: unknown): s is ? => typeof s === 'string'; // Infer => is string
function isStringOrNumber(s: unknown): s is ? { // Infer => is string | number
  if (typeof s === 'number)
    return true;
  return typeof s === 'string';
}
function hasA(s: { a: number } | { b: string }): s is ? => 'a' in s; // Infer => ({ a: number } | { b: string }) & { a: unknown }

This would be slightly useful, for example if the last function was mistyped as => 'a1' in s, the inferred type would be ({ a: number } | { b: string }) & { a1: unknown }, and the error would be obvious when this function was used.

but what would make it really useful is if it can be used in lambdas, such as Array.prototype.filter(), like

const source = ['a', null, 'b'];
const values = source.filter(s => !!s);
for (const v of values) {
  f(v); // Should work
}
function f(s: string) {}

This example would work if:

  1. We have the feature mentioned above 😊
  2. The overload resolution would see that there is a method (which already is there today) filter<S extends T>(predicate: (value: T) => value is S): S[];
  3. The compiler would then look at the body and run the type guard inference to see what it can say about the predicate. In this case it would be able to treat it as .filter((s): s is (string | null) & {} => !!s)

πŸ’» Use Cases

  1. What do you want to use this for?

Mainly methods like, Array.prototype.filter

  1. What shortcomings exist with current approaches?

The current method of doing it is not perfectly ergonomic, and the checker could be more clever.

  1. What workarounds are you using in the meantime?
function f(s: string) {}
const source = ['a', null, 'b'];
const values1 = source.filter((s): s is string => !!s);
const values2 = source.filter(s => !!s);
f(values1[0]); // This works
f(values2[0]!); // So does this

Both ways work, but the first requires me to specify something that the compiler can figure out by itself, and the second requires an unnecessary non-null assertions (which is also forbidden by my eslint configuration so I also need to disable that).

@MartinJohns
Copy link
Contributor

I'd say it's essentially a duplicate of #38390.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Feb 1, 2024
@typescript-bot
Copy link
Collaborator

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

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Feb 4, 2024
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