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

no-useless-assertion: disallow literal type assertion when compiler can infer correct type #272

Open
ajafff opened this issue Jun 1, 2018 · 2 comments

Comments

@ajafff
Copy link
Member

ajafff commented Jun 1, 2018

[email protected] no longer widens literal types if the type parameter is constrained with at least one primitive type.

microsoft/TypeScript#24310

declare let cond: boolean;

declare function identity<T>(x: T): T;
declare function widening<T>(x: T): {prop: T};
declare function nonWidening<T extends string | number | symbol>(x: T): {prop: T};

// this already works in older versions
const v1 = identity('a'); // "a"
const v2 = identity(10); // 10
const v3 = identity(cond ? 'a' : 10); // "a" | 10

// unchanged
const x1 = widening('a');  // string
const x2 = widening(10);  // number
const x3 = widening(cond ? 'a' : 10);  // string | number

// new in 2.9
const y1 = nonWidening('a');  // "a"
const y2 = nonWidening(10);  // 10
const y3 = nonWidening(cond ? 'a' : 10);  // "a" | 10

Therefore:

identity('a' as 'a'); // lint error in all typescript versions
widening('a' as 'a'); // no error
nonWidening('a' as 'a'); // lint error starting from 2.9

// also handle these cases
identity(cond ? 'a' as 'a' : 10 as 10);

declare function arr<T extends string | number>(...params: T[]): T[];
arr(1 as 1, 2 as 2, 3 as 3);

On a related note: I don't really know what the PR above changed. It seems everything already worked as expected before that change ...

@ajafff
Copy link
Member Author

ajafff commented Jun 1, 2018

It turns out the PR linked above doesn't really do what I expected.

In fact the rule that applies here is way more simple than described above:
If an expression has a non-widening type, there's no need for an assertion. See microsoft/TypeScript#11126 for an explanation of widening types.

@ajafff
Copy link
Member Author

ajafff commented Jun 7, 2018

It turns out the type system is not really helpful here. Because getWidenedLiteralType and ts.TypeFlags.FreshLiteral are not exposed, there's no way to know if a type is a non-widening type.

For now this will probably only work for contextual types that are type parameters with a primitive type in their constraint. This also requires #282 to be implemented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant