Skip to content

fix(eslint-plugin): [no-unnecessary-template-expression] handle template literal type #10612

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

Merged
merged 12 commits into from
Jan 27, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ The new name is a drop-in replacement with identical functionality.

const ab1 = `${'a'}${'b'}`;
const ab2 = `a${'b'}`;
type AB1 = `${'A'}${'B'}`;
type AB2 = `A${'B'}`;

const stringWithNumber = `${'1 + 1 = '}${2}`;

Expand All @@ -38,9 +40,13 @@ const stringWithBoolean = `${'true is '}${true}`;

const text = 'a';
const wrappedText = `${text}`;
type Text = 'A';
type WrappedText = `${Text}`;

declare const intersectionWithString: string & { _brand: 'test-brand' };
const wrappedIntersection = `${intersectionWithString}`;
type IntersectionWithString = string & { _brand: 'test-brand' };
type WrappedIntersection = `${IntersectionWithString}`;
```

</TabItem>
Expand All @@ -51,6 +57,15 @@ const wrappedIntersection = `${intersectionWithString}`;

const ab1 = `ab`;
const ab2 = `ab`;
type AB = `AB`;

// Transforming enum members into string unions using template literals is allowed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, what's the reasoning for this? I'm not familiar with this usage, so I'm curious for a reference on it, and not seeing one on the issue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kirkwaiblinger
I should have written an explanation for this, but I missed it. This is an easy way to change an enum to a union type, and the union type is not the same as the enum.

playground

enum Enum {
  A = 'A',
  B = 'B',
  C = 'C'
}

type Union = `${Enum}`;

function foo(a: Enum) {}

foo("A"); // ts error: Argument of type '"A"' is not assignable to parameter of type 'EnumA'.
foo(Enum.A);


function bar(a: Union) {}

bar("A");

typescript-eslint is also using this approach.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok 👍 Seems plausible to me! I'll defer to you and other reviewers on this, thanks for the explanation!

enum ABC {
A = 'A',
B = 'B',
C = 'C',
}
type ABCUnion = `${ABC}`;

const stringWithNumber = `1 + 1 = 2`;

Expand All @@ -61,9 +76,13 @@ const stringWithBoolean = `true is true`;

const text = 'a';
const wrappedText = text;
type Text = 'A';
type WrappedText = Text;

declare const intersectionWithString: string & { _brand: 'test-brand' };
const wrappedIntersection = intersectionWithString;
type IntersectionWithString = string & { _brand: 'test-brand' };
type WrappedIntersection = IntersectionWithString;
```

</TabItem>
Expand Down
Loading
Loading