現在多數 React 前端職缺都會要求 TypeScript,但面試通常不只問「有沒有用過」。
常見追問會是:
any和unknown差在哪?never什麼時候會出現?type和interface怎麼選?- 泛型解決什麼問題?
- API response 可以直接
as User嗎?
any 和 unknown 差在哪?
any 代表放棄型別檢查。
let value: any = "hello";
value.foo.bar();TypeScript 不會阻止這段程式,但 runtime 很可能出錯。
unknown 則代表「目前不知道是什麼」,使用前必須先縮小型別:
let value: unknown = "hello";
if (typeof value === "string") {
console.log(value.toUpperCase());
}面試可以這樣回答:
any 會關閉型別檢查,unknown 則要求使用前先做 type narrowing。處理外部輸入、catch error 或第三方資料時,我會優先用 unknown。
never 是什麼?
never 代表永遠不會產生值。
永遠拋出錯誤的函式:
function fail(message: string): never {
throw new Error(message);
}它也很適合做 exhaustive check:
type Status = "idle" | "loading" | "success" | "error";
function getLabel(status: Status) {
switch (status) {
case "idle":
return "尚未開始";
case "loading":
return "載入中";
case "success":
return "完成";
case "error":
return "失敗";
default: {
const unreachable: never = status;
return unreachable;
}
}
}未來如果新增 status 卻忘記處理,TypeScript 就會提醒。
type 和 interface 怎麼選?
兩者都能描述 object shape:
interface User {
id: string;
name: string;
}
type Product = {
id: string;
price: number;
};常見差異:
interface支援 declaration mergingtype可以表達 union、tuple、mapped type- 兩者都能 extend / compose,只是語法不同
實務上比起爭論哪個一定比較好,更重要的是團隊一致。
泛型解決什麼問題?
泛型讓型別可以保留輸入與輸出的關係。
function first<T>(items: T[]): T | undefined {
return items[0];
}
const user = first<User>(users);
const product = first<Product>(products);如果用 any,型別資訊會消失;泛型則能重用邏輯又保留型別安全。
API response 也常用泛型:
type ApiResponse<T> = {
data: T;
message: string;
};
type UserResponse = ApiResponse<User>;常見 Utility Types
| Utility Type | 用途 |
|---|---|
Partial<T> | 所有欄位變 optional |
Required<T> | 所有欄位變 required |
Pick<T, K> | 選出部分欄位 |
Omit<T, K> | 排除部分欄位 |
Record<K, V> | 建立 key-value object |
Readonly<T> | 欄位不能重新賦值 |
type UserForm = Pick<User, "name" | "email">;
type UserPatch = Partial<UserForm>;API response 可以直接 as User 嗎?
const data = (await response.json()) as User;這只是在告訴 TypeScript「相信我」,不會在 runtime 驗證資料。
如果後端少回欄位或型別錯誤,TypeScript 也救不了。
更安全的做法是用 schema validator,例如 Zod,或自己寫 type guard:
function isUser(value: unknown): value is User {
if (typeof value !== "object" || value === null) return false;
const user = value as Record<string, unknown>;
return typeof user.id === "string" && typeof user.name === "string";
}面試回答模板
TypeScript 的價值不只是補型別,而是讓資料關係和可能狀態在編譯期可被檢查。any 會跳過檢查,unknown 則要求先 narrowing;never 可以做 exhaustive check;泛型能重用邏輯並保留輸入輸出的型別關係。對 API response,我不會只依賴 type assertion,重要資料會搭配 runtime schema validation。