Skip to content

ts-ignore: Allow specifying maximum typescript versionย #62555

@jtannas

Description

@jtannas

๐Ÿ” Search Terms

"ts-ignore", "version", "ts-expect-error"

โœ… Viability Checklist

โญ 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:

https://evanhahn.com/ts-ignore-is-almost-always-the-worst-option/#the-once-edge-case-when-ts-ignore-might-be-optimal:~:text=The%20one%20edge,ts%2Dignore%20compelling.

For example, imagine youโ€™re writing a library that supports old versions of TypeScript, before they added the unknown type. If you try to use unknown, youโ€™ll get errors in old TypeScript versions but not new ones. @ts-ignore may 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-ignore is present. e.g.:
    • satisfies in versions < 4.9
    • template literal types in versions < 4.1
    • import type in 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

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 generates TS2578: Unused '@ts-expect-error' directive.
By not including TS2578 in the ignore codes, you replicate the effect of @ts-expect-error using the @ts-ignore-{} syntax.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions