chore: enable typescript/restrict-template-expressions lint rule (#12199)

* chore: enable typescript/restrict-template-expressions lint rule

Coerce values of unknown type with explicit String() and tighten typing
for template literal expressions across the codebase.

* fix: restore --line-height on Card for fadeOut ::after gradient
This commit is contained in:
Tom Moor
2026-04-28 20:11:15 -04:00
committed by GitHub
parent adbffc0734
commit 87bb79250d
13 changed files with 27 additions and 27 deletions
+1
View File
@@ -91,6 +91,7 @@
"import/no-named-as-default": "off",
"import/no-named-as-default-member": "off",
"typescript/consistent-type-imports": "error",
"typescript/restrict-template-expressions": "error",
"typescript/no-floating-promises": "error",
"no-unused-vars": [
"error",
+1 -1
View File
@@ -88,6 +88,7 @@ export const CardContent = styled.div`
// &:after — gradient mask for overflow text
export const Card = styled.div<{ fadeOut?: boolean; $borderRadius?: string }>`
${sharedVars}
backdrop-filter: blur(10px);
background: ${s("menuBackground")};
padding: 16px;
@@ -112,7 +113,6 @@ export const Card = styled.div<{ fadeOut?: boolean; $borderRadius?: string }>`
${(props) =>
props.fadeOut !== false
? `&:after {
${sharedVars}
content: "";
display: block;
position: absolute;
+10 -10
View File
@@ -42,7 +42,7 @@ export function toMenuItems(items: MenuItem[]) {
case "button":
return (
<MenuButton
key={`${item.type}-${item.title}-${index}`}
key={`${item.type}-${index}`}
label={item.title as string}
icon={icon}
disabled={item.disabled}
@@ -57,7 +57,7 @@ export function toMenuItems(items: MenuItem[]) {
case "route":
return (
<MenuInternalLink
key={`${item.type}-${item.title}-${index}`}
key={`${item.type}-${index}`}
label={item.title as string}
icon={icon}
disabled={item.disabled}
@@ -69,7 +69,7 @@ export function toMenuItems(items: MenuItem[]) {
case "link":
return (
<MenuExternalLink
key={`${item.type}-${item.title}-${index}`}
key={`${item.type}-${index}`}
label={item.title as string}
icon={icon}
disabled={item.disabled}
@@ -95,7 +95,7 @@ export function toMenuItems(items: MenuItem[]) {
};
return (
<SubMenu key={`${item.type}-${item.title}-${index}`}>
<SubMenu key={`${item.type}-${index}`}>
<SubMenuTrigger
label={item.title as string}
icon={icon}
@@ -121,7 +121,7 @@ export function toMenuItems(items: MenuItem[]) {
return (
<MenuGroup
key={`${item.type}-${item.title}-${index}`}
key={`${item.type}-${index}`}
label={item.title as string}
items={groupItems}
/>
@@ -171,7 +171,7 @@ export function toMobileMenuItems(
case "button":
return (
<Components.MenuButton
key={`${item.type}-${item.title}-${index}`}
key={`${item.type}-${index}`}
disabled={item.disabled}
$dangerous={item.dangerous}
onClick={(e) => {
@@ -192,7 +192,7 @@ export function toMobileMenuItems(
case "route":
return (
<Components.MenuInternalLink
key={`${item.type}-${item.title}-${index}`}
key={`${item.type}-${index}`}
to={item.to}
disabled={item.disabled}
onClick={closeMenu}
@@ -205,7 +205,7 @@ export function toMobileMenuItems(
case "link":
return (
<Components.MenuExternalLink
key={`${item.type}-${item.title}-${index}`}
key={`${item.type}-${index}`}
href={typeof item.href === "string" ? item.href : item.href.url}
target={
typeof item.href === "string" ? undefined : item.href.target
@@ -231,7 +231,7 @@ export function toMobileMenuItems(
return (
<Components.MenuButton
key={`${item.type}-${item.title}-${index}`}
key={`${item.type}-${index}`}
disabled={item.disabled}
onClick={() => {
openSubmenu(item.title as string);
@@ -256,7 +256,7 @@ export function toMobileMenuItems(
}
return (
<div key={`${item.type}-${item.title}-${index}`}>
<div key={`${item.type}-${index}`}>
<Components.MenuHeader>{item.title}</Components.MenuHeader>
{groupItems}
</div>
+1 -2
View File
@@ -1,12 +1,11 @@
import { observer } from "mobx-react";
import * as React from "react";
import { Helmet } from "react-helmet-async";
import env from "~/env";
import useStores from "~/hooks/useStores";
import { useTeamContext } from "./TeamContext";
type Props = {
title: React.ReactNode;
title: string;
favicon?: string;
};
+1 -1
View File
@@ -34,7 +34,7 @@ const Scene: React.FC<Props> = ({
wide,
}: Props) => (
<FillWidth>
<PageTitle title={textTitle || title} />
<PageTitle title={textTitle ?? (typeof title === "string" ? title : "")} />
<Header
hasSidebar
title={
+1 -1
View File
@@ -116,7 +116,7 @@ export class GitHubIssueProvider extends BaseIssueProvider {
const installation = await client.requestAppInstallation(installationId);
const scopes = Object.entries(installation.data.permissions).map(
([name, permission]) => `${name}:${permission}`
([name, permission]) => `${name}:${String(permission)}`
);
await sequelize.transaction(async (transaction) => {
+1 -1
View File
@@ -64,7 +64,7 @@ router.get(
}
const scopes = Object.entries(installation.permissions).map(
([name, permission]) => `${name}:${permission}`
([name, permission]) => `${name}:${String(permission)}`
);
const authentication = await IntegrationAuthentication.create(
+2 -2
View File
@@ -60,8 +60,8 @@ class Logger {
winston.format.printf(
({ message, level, label, ...extra }) =>
`${level}: ${
label ? styleText("bold", `[${label}] `) : ""
}${message} ${isEmpty(extra) ? "" : JSON.stringify(extra)}`
label ? styleText("bold", `[${String(label)}] `) : ""
}${String(message)} ${isEmpty(extra) ? "" : JSON.stringify(extra)}`
)
),
})
+1 -1
View File
@@ -75,7 +75,7 @@ export function defaultRateLimiter() {
ctx.set("RateLimit-Remaining", `${rateLimiterRes.remainingPoints}`);
ctx.set(
"RateLimit-Reset",
`${new Date(Date.now() + rateLimiterRes.msBeforeNext)}`
new Date(Date.now() + rateLimiterRes.msBeforeNext).toString()
);
Metrics.increment("rate_limit.exceeded", {
+2 -2
View File
@@ -36,9 +36,9 @@ export function CounterCache<
setImmediate(() => {
const recalculateCache =
(offset: number) => async (model: InstanceType<T>) => {
const cacheKey = `${cacheKeyPrefix}:${
const cacheKey = `${cacheKeyPrefix}:${String(
model[options.foreignKey as keyof typeof model]
}`;
)}`;
const count = await modelClass.count({
where: {
+1 -1
View File
@@ -31,7 +31,7 @@ export function createQueue(
});
default:
throw new Error(`Unexpected connection type: ${type}`);
throw new Error(`Unexpected connection type: ${String(type)}`);
}
},
defaultJobOptions: {
+4 -4
View File
@@ -214,15 +214,15 @@ export function createMigrationRunner(
Logger.info(
"database",
params.event === "migrating"
? `Migrating ${params.name}`
: `Migrated ${params.name} in ${params.durationSeconds}s`
? `Migrating ${String(params.name)}`
: `Migrated ${String(params.name)} in ${String(params.durationSeconds)}s`
),
debug: (params) =>
Logger.debug(
"database",
params.event === "migrating"
? `Migrating ${params.name}`
: `Migrated ${params.name} in ${params.durationSeconds}s`
? `Migrating ${String(params.name)}`
: `Migrated ${String(params.name)} in ${String(params.durationSeconds)}s`
),
},
});
+1 -1
View File
@@ -23,7 +23,7 @@ export class TestError extends Error {
public actual: unknown,
public expected: unknown
) {
super(`Test failed: ${actual} != ${expected}`);
super(`Test failed: ${String(actual)} != ${String(expected)}`);
this.name = "TestError";
}
}