Loading...
Loading...
Compare original and translation side by side
Project setup — readwhen bootstrapping a new project or changing tsconfig / ts-reset / type-fest. ESLint baseline — readproject-setup.mdwhen adding or tweaking lint rules.eslint.config.mjs
项目设置 — 当启动新项目或修改tsconfig、ts-reset、type-fest时,请阅读。 ESLint 基准配置 — 当添加或调整 lint 规则时,请阅读project-setup.md。eslint.config.mjs
// GOOD — each variant carries exactly its data
type Result =
| { status: "ok"; data: string }
| { status: "error"; message: string };
// Exhaustive check helper — will fail to compile if a variant is missed
function assertNever(x: never): never {
throw new Error(`Unexpected: ${JSON.stringify(x)}`);
}
function handle(r: Result) {
switch (r.status) {
case "ok": return r.data;
case "error": return r.message;
default: assertNever(r); // compile error if a case is missing
}
}satisfies neverassertNeverdefault:switch-exhaustiveness-check// GOOD — each variant carries exactly its data
type Result =
| { status: "ok"; data: string }
| { status: "error"; message: string };
// Exhaustive check helper — will fail to compile if a variant is missed
function assertNever(x: never): never {
throw new Error(`Unexpected: ${JSON.stringify(x)}`);
}
function handle(r: Result) {
switch (r.status) {
case "ok": return r.data;
case "error": return r.message;
default: assertNever(r); // compile error if a case is missing
}
}default:satisfies neverassertNeverswitch-exhaustiveness-checktype Brand<T, B extends string> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
type OrderId = Brand<string, "OrderId">;
function getUser(id: UserId) { /* ... */ }
const uid = "abc" as UserId; // cast once at the boundary
getUser(uid); // OK
getUser("abc"); // compile error — plain string is not UserIdtype Brand<T, B extends string> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
type OrderId = Brand<string, "OrderId">;
function getUser(id: UserId) { /* ... */ }
const uid = "abc" as UserId; // cast once at the boundary
getUser(uid); // OK
getUser("abc"); // compile error — plain string is not UserIdtype HexColor = `#${string}`;
type Route = `/${string}`;
type EventName = `on${Capitalize<string>}`;
function setColor(c: HexColor) { /* ... */ }
setColor("#ff0000"); // OK
setColor("red"); // compile errortype HexColor = `#${string}`;
type Route = `/${string}`;
type EventName = `on${Capitalize<string>}`;
function setColor(c: HexColor) { /* ... */ }
setColor("#ff0000"); // OK
setColor("red"); // compile error!as!as!asobj.prop!const { name = '' } = config;.at()arr[0]!const first = arr.at(0) ?? fallback;value as Foo!asobj.prop!const { name = '' } = config;.at()arr[0]!const first = arr.at(0) ?? fallback;value as Fooenumas constconst STATUSES = ["pending", "active", "done"] as const;
type Status = (typeof STATUSES)[number];z.enum(STATUSES)enumas constconst STATUSES = ["pending", "active", "done"] as const;
type Status = (typeof STATUSES)[number];z.enum(STATUSES)z.infer<>export const sessionMetaSchema = z.object({
token: z.string(),
status: z.enum(["running", "completed", "error"]),
});
export type SessionMeta = z.infer<typeof sessionMetaSchema>;safeParse()parse()z.infer<>export const sessionMetaSchema = z.object({
token: z.string(),
status: z.enum(["running", "completed", "error"]),
});
export type SessionMeta = z.infer<typeof sessionMetaSchema>;safeParse()parse()noUncheckedIndexedAccessT | undefined.at(index)if (item !== undefined)??.find().filter()noUncheckedIndexedAccessT | undefined.at(index)if (item !== undefined)??.find().filter()SetRequiredSimplifyJsonValuesrc/types/SetRequiredSimplifyJsonValuesrc/types/