Kodokon kodokon.com

tsconfig แบบ strict: ตัวเลือกสำคัญและ error ที่พบบ่อย

คุณจะเข้าใจว่า strict mode เปิดใช้อะไรจริง ๆ และรู้วิธีรับมือกับ error ทั่วไปที่มันเผยออกมาในโปรเจกต์ที่มีอยู่

11 นาที · 3 คำถาม

เปิดบทเรียนนี้ใน Kodokon

"strict": true ไม่ใช่ตัวเลือกเดียวแต่เป็น กลุ่มรวม ที่เปิดใช้การตรวจสอบทั้งตระกูล: strictNullChecks, noImplicitAny, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables และ alwaysStrict TypeScript เวอร์ชันใหม่แต่ละรุ่นอาจเพิ่มเข้ามาอีก: การเปิด strict เท่ากับสมัครรับการตรวจสอบในอนาคต แต่ละ flag ยังปิดแยกเดี่ยวได้ ซึ่งช่วยให้ย้ายระบบทีละขั้นบน codebase ที่มีอยู่

JSON
{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "noFallthroughCasesInSwitch": true,
    "exactOptionalPropertyTypes": true,
    "verbatimModuleSyntax": true,
    "skipLibCheck": true
  }
}
baseline แบบ strict ที่ขยายด้วยตัวเลือกนอกกลุ่มรวม (ไฟล์ JSON)

flag ที่มีผลกระทบสูงสุดสองตัวคือ strictNullChecks และ noImplicitAny ตัวแรกเอา null และ undefined ออกจากทุกชนิด: ทุกค่าที่อาจไม่มีอยู่ต้องประกาศเป็น T | undefined และจัดการก่อนใช้ ตัวที่สองปฏิเสธไม่ให้พารามิเตอร์ที่ไม่ได้ annotate ย้อนกลับเป็น any เมื่อรวมกัน ทั้งสองกำจัดบั๊กสองตระกูลใหญ่ของ JavaScript: "cannot read property of undefined" และการแพร่กระจายของค่าที่ไม่ถูกตรวจสอบ useUnknownInCatchVariables เติมภาพให้สมบูรณ์: ตัวแปรใน catch เป็น unknown เพราะ JavaScript ยอมให้คุณ throw อะไรก็ได้

TYPESCRIPT
function findPort(
  env: Record<string, string | undefined>
): number {
  const raw = env["PORT"];
  if (raw === undefined) {
    return 3000;
  }
  return Number.parseInt(raw, 10);
}

declare function riskyOperation(): void;

try {
  riskyOperation();
} catch (err) {
  const message =
    err instanceof Error ? err.message : String(err);
  console.error(message);
}
สองรูปแบบแบบ strict: จัดการการไม่มีอยู่ และ catch เป็น unknown

error ในการย้ายระบบที่พบบ่อยและวิธีแก้ที่แท้จริง "Object is possibly undefined": ให้เลือก narrow (if), optional chaining ?. หรือค่าเริ่มต้นด้วย ?? แทน non-null assertion ! ซึ่งเพียงย้ายจุดพังไปที่อื่น "Property has no initializer" (strictPropertyInitialization): ให้กำหนดค่าเริ่มต้นใน constructor แทนที่จะคว้า ! มาใส่ที่ฟิลด์ และระวังกับดัก ?? กับ || ด้วย: port || 3000 จะแทนที่ 0 และ "" ด้วย ในขณะที่ port ?? 3000 แทนที่เฉพาะ null และ undefined เท่านั้น

TYPESCRIPT
interface Settings { retries?: number }

function resolveRetries(s: Settings): number {
  const bad = s.retries || 3;
  const good = s.retries ?? 3;
  return good;
}

const names = ["Ada", "Linus"];
const first = names[0];
const upper = first?.toUpperCase() ?? "N/A";
retries: 0 ทำให้ bad = 3 แต่ good = 0; การเข้าถึงด้วย index ถูกตรวจในลำดับถัดไป

นอกเหนือจากกลุ่มรวม มีสามตัวเลือกที่ควรนำมาหารือในทีม noUncheckedIndexedAccess เพิ่ม undefined ให้ทุกการเข้าถึงด้วย index (arr[i], dict[key]): ปลอดภัยกว่าแต่เยิ่นเย้อในโค้ดที่จัดการ array - หลายทีมจึงนำมาใช้เฉพาะกับโปรเจกต์ใหม่ exactOptionalPropertyTypes แยกแยะระหว่าง "property ไม่มีอยู่" กับ "property ตั้งเป็น undefined" ซึ่งสำคัญยิ่งสำหรับ patch skipLibCheck ข้ามการตรวจไฟล์ .d.ts ของ dependency ของคุณ: เป็นการแลกเปลี่ยนที่จงใจระหว่างเวลา build กับการตรวจพบความขัดแย้งระหว่างไลบรารี

ทดสอบความรู้

ตรวจสอบว่าคุณจำประเด็นสำคัญของบทเรียนนี้ได้ครบถ้วน

  1. "strict": true ใน tsconfig.json ทำอะไรกันแน่?
    • มันเปิดเฉพาะตัวเลือก strictNullChecks
    • มันเปิดชุดของ flag แบบ strict ซึ่งแต่ละตัวยังปิดแยกเดี่ยวได้
    • มันห้ามใช้ชนิด any ใด ๆ แม้แต่แบบระบุชัดเจน
    • มันบังคับให้คอมไพล์ในโหมด ES5
  2. เมื่อ retries?: number ถูกตั้งเป็น 0 อะไรคือความแตกต่างระหว่าง retries || 3 และ retries ?? 3?
    • ไม่ต่างกัน ทั้งคู่คืน 0
    • || คืน 3 เพราะ 0 เป็น falsy; ?? คืน 0 เพราะมันแทนที่เฉพาะ null และ undefined
    • ?? คืน 3 เพราะ 0 ถูกถือว่าไม่มีอยู่
  3. ทำไมจึงควรเลือก // @ts-expect-error แทน // @ts-ignore ในการระบุหนี้ด้านการกำหนดชนิด?
    • @ts-expect-error กด error ได้หลายตัวพร้อมกัน
    • @ts-ignore ใช้ไม่ได้ใน strict mode
    • @ts-expect-error กลายเป็น error เมื่อปัญหาถูกแก้ ดังนั้นหนี้จึงล้างตัวมันเอง