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

infer extends number in conditional type handles '\n' incorrectly #50137

Open
yenshih opened this issue Aug 2, 2022 · 10 comments
Open

infer extends number in conditional type handles '\n' incorrectly #50137

yenshih opened this issue Aug 2, 2022 · 10 comments
Assignees
Labels
Bug A bug in TypeScript Rescheduled This issue was previously scheduled to an earlier milestone

Comments

@yenshih
Copy link

yenshih commented Aug 2, 2022

Bug Report

πŸ”Ž Search Terms

  • infer extends number

πŸ•— Version & Regression Information

4.8.0-beta (in playground)

⏯ Playground Link

Playground link with relevant code

A simple type-level JSON parser encounters this issue

πŸ’» Code

// number
type Foo = '\n' extends `${infer T extends number}${infer R}` ? T : never;

πŸ™ Actual behavior

Foo is number

πŸ™‚ Expected behavior

Foo should be never

@Josh-Cena
Copy link
Contributor

@yenshih
Copy link
Author

yenshih commented Aug 2, 2022

It doesn't make sense...
It is definitely counterintuitive :(

@Josh-Cena
Copy link
Contributor

Josh-Cena commented Aug 2, 2022

Same feeling. It's a valid JS StringNumericLiteral production regardless, which means if you have Number(" ") it gives you 0 instead of NaN. The inconsistency is that "" is not a valid `${number}` while being a valid StringNumericLiteral.

@MartinJohns
Copy link
Contributor

IIRC you can pass anything that is compatible with parseInt(). There was an issue about this, but I can't find it right now.

@Josh-Cena
Copy link
Contributor

Josh-Cena commented Aug 2, 2022

Not just parseInt()β€”but Number(). It uses the StringNumericLiteral production, which means 0b111 is a `${number}` as well. (Disclaimer: didn't read that source code; this is based on experiment).

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Aug 2, 2022
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 4.9.0 milestone Aug 2, 2022
@RyanCavanaugh
Copy link
Member

@ahejlsberg this seems like wrong behavior - can you confirm?

@fatcerberus
Copy link

fatcerberus commented Aug 2, 2022

I would like to point out that due to the consecutive placeholders...

type Foo = '812' extends `${infer T extends number}${infer R}` ? T : never;
//   ^? type Foo = 8

...infer T will only ever match the first digit. There's an issue about this (it's by design) but I can never find it when I need to. It even affects cases like `${number}${string}` where you might expect it to be greedy 🐽

@whzx5byb
Copy link

whzx5byb commented Aug 2, 2022

@fatcerberus You are looking for #46124 (comment) ?

@ahejlsberg
Copy link
Member

@RyanCavanaugh It does seem like odd behavior, but the expression +s produces 0 when s is just whitespace, and so far we've said that any finite number result from +s is acceptable. I suppose we could additionally validate that s isn't just whitespace.

@RyanCavanaugh RyanCavanaugh added the Rescheduled This issue was previously scheduled to an earlier milestone label Feb 1, 2023
@dimitropoulos
Copy link
Contributor

dimitropoulos commented Feb 14, 2024

by the way, for whoever does this (can I do it? seems really small?) I happened to notice that it's not just empty whitespace you gotta check for, but also whitespace that surrounds (otherwise valid) numbers. So 00 works, as does 00 , 001 , or any hex/octal/binary/scientific notation. You can get silly and add lots of junk:

type Foo = ' \t\n001234e1\r\u0020\u2029 ' extends `${infer T extends number}` ? T : never;
//   ^? number

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Rescheduled This issue was previously scheduled to an earlier milestone
Projects
None yet
Development

No branches or pull requests

8 participants