microsoft / microsoft/TypeScript
`ts-ignore`: Allow specifying maximum typescript version
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 132
Description
🔍 Search Terms
"ts-ignore", "version", "ts-expect-error"
✅ Viability Checklist
- 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 isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
⭐ Suggestion
Allow @ts-ignore to specify the maximum version of typescript that it applies to.
Example:
// @ts-ignore version<4.0
Inequalities might also be worth implementing:
// @ts-ignore version>4.0
// @ts-ignore version!=4.0
📃 Motivating Example
This is inspired by the use case of ts-ignore detailed in the following article written by Evan Hahn:
For example, imagine you’re writing a library that supports old versions of TypeScript, before they added the
unknowntype. If you try to useunknown, you’ll get errors in old TypeScript versions but not new ones.@ts-ignoremay be the right option here, because it’ll work in both versions (unlike the alternatives).
// Using `ts-expect-error`, this:
// - fails on TS versions <3.9 (when `ts-expect-error` was introduced)
// - works from versions 3.9 to <4.5
// - fails for versions >=4.5 (when `Awaited`/`Promise` were introduced)
// @ts-expect-error
type A = Awaited<Promise<string>>;
// This works on all TS versions >=2.6 when `ts-ignore` was introduced:
// @ts-ignore
type A = Awaited<Promise<string>>;
With this new extension to ts-ignore, library authors can get the type-safety of modern TypeScript without impacting users running older TS versions.
💻 Use Cases
What this helps with
For libraries supporting TS>=2.6 (when @ts-ignore was introduced), it allows using newer keywords without disabling TS on versions that support the new syntax:
// @ts-ignore version<3.0
const foo: unknown = {}
// @ts-ignore version<4.5
type A = Awaited<Promise<string>>;
Versions of TypeScript that support the ts-ignore but predate this new feature already just ignore the version specifier as if it were a comment. This ensures that no existing code will break.
What this does not help with
- Libraries that have to support TypeScript versions predating
@ts-ignore(<2.6). - New syntax that fails even when
@ts-ignoreis present. e.g.:satisfiesin versions < 4.9- template literal types in versions < 4.1
import typein versions < 3.8
Why not apply this to @ts-expect-error too?
Imagine you're writing a library which requires a TS version >=4.1.
You're personally developing on the latest version and it has the new feature introduced in 6.0.
You decide you want to use the v4.5 Awaited/Promise utility types but you know the people running TS 4.1 don't have them yet. You try out the new version specifier on @ts-expect-error. This happens:
// This
// - works from versions 4.1 to <4.5 because the `ts-expect-error`
// - fails for versions >=4.5 to <6.0 because it doesn't know to ignore those versions
// - works for versions >=6.0 because it now correctly interprets the version tag
// @ts-expect-error version<4.1
type A = Awaited<Promise<string>>;
You end up making the problem worse instead of better 😖
This turns the @ts-expect-error version into a footgun for as long as people are commonly running TS versions that don't support the feature.
Related Issues
- https://github.com/microsoft/TypeScript/issues/45937
- https://github.com/microsoft/TypeScript/issues/19139
It seems there is a general appetite to have more nuanced control over ts-ignore and ts-expect-error.
It might be worth considering a syntax that allows for different flags.
Off the top of my head... Something based on JS object notation feels like it has potential: @ts-ignore-{}
// TS2322: Type 'string' is not assignable to type 'number'.
// @ts-ignore-{version: "<4.1", codes: ["TS2322"]}
const a: number = 'foo'
[!NOTE]
This could be used as an alternative to@ts-expect-error.
An unused expect error generatesTS2578: Unused '@ts-expect-error' directive.
By not includingTS2578in the ignore codes, you replicate the effect of@ts-expect-errorusing the@ts-ignore-{}syntax.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The issue names @ts-ignore and @ts-expect-error but does not identify files, tests, or entry points. Start by locating the compiler's handling of these directives and review the related issues for design context. Done should include an agreed version-specifier syntax and behavior for supported and unsupported TypeScript versions, with tests for the proposed inequalities.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100