ไทย

เชี่ยวชาญการตั้งค่า TypeScript ด้วยคู่มือ tsconfig.json ฉบับลึกนี้ เรียนรู้ตัวเลือกคอมไพเลอร์ที่สำคัญ การตั้งค่าโปรเจกต์ และการกำหนดค่าขั้นสูงเพื่อการพัฒนาที่มีประสิทธิภาพ

การตั้งค่า TypeScript: คู่มือฉบับสมบูรณ์สำหรับ tsconfig.json

TypeScript ซึ่งเป็นส่วนขยายของ JavaScript (superset) นำระบบการกำหนดชนิดข้อมูลแบบสถิต (static typing) มาสู่โลกของการพัฒนาเว็บที่เปลี่ยนแปลงตลอดเวลา ไฟล์ tsconfig.json ที่ตั้งค่าอย่างดีมีความสำคัญอย่างยิ่งต่อการดึงศักยภาพสูงสุดของ TypeScript ออกมาใช้งาน คู่มือนี้จะให้ภาพรวมที่ครอบคลุมเกี่ยวกับ tsconfig.json โดยจะกล่าวถึงตัวเลือกคอมไพเลอร์ที่จำเป็น การตั้งค่าโปรเจกต์ และการกำหนดค่าขั้นสูง

tsconfig.json คืออะไร?

ไฟล์ tsconfig.json คือไฟล์การกำหนดค่าที่ระบุตัวเลือกของคอมไพเลอร์ (compiler options) สำหรับโปรเจกต์ TypeScript มันจะบอกคอมไพเลอร์ของ TypeScript ว่าจะแปลง (transpile) โค้ด TypeScript เป็น JavaScript อย่างไร ไฟล์นี้มีความจำเป็นสำหรับการกำหนดโครงสร้างของโปรเจกต์ การตั้งค่ากฎการคอมไพล์ และสร้างความสอดคล้องกันภายในทีมพัฒนา ไม่ว่าทีมนั้นจะทำงานอยู่ในออฟฟิศแห่งเดียวหรือกระจายตัวอยู่ตามทวีปต่างๆ

การสร้างไฟล์ tsconfig.json

ในการสร้างไฟล์ tsconfig.json ให้ไปที่ไดเรกทอรีราก (root directory) ของโปรเจกต์ในเทอร์มินัลแล้วรันคำสั่งต่อไปนี้:

tsc --init

คำสั่งนี้จะสร้างไฟล์ tsconfig.json พื้นฐานพร้อมกับตัวเลือกคอมไพเลอร์ที่ใช้กันทั่วไป จากนั้นคุณสามารถปรับแต่งไฟล์ให้เหมาะกับความต้องการเฉพาะของโปรเจกต์ของคุณได้ โดยทั่วไปแล้ว tsconfig.json จะมีตัวเลือกต่างๆ เช่น compilerOptions, include, และ exclude

ตัวเลือกคอมไพเลอร์ที่สำคัญ

ส่วนของ compilerOptions คือหัวใจของไฟล์ tsconfig.json ซึ่งประกอบด้วยตัวเลือกมากมายที่ควบคุมการทำงานของคอมไพเลอร์ TypeScript นี่คือตัวเลือกคอมไพเลอร์ที่สำคัญที่สุดบางส่วน:

target

ตัวเลือก target ใช้ระบุเวอร์ชันเป้าหมายของ ECMAScript สำหรับโค้ด JavaScript ที่จะถูกสร้างขึ้น ค่าที่ใช้กันทั่วไปได้แก่ ES5, ES6 (ES2015), ES2016, ES2017, ES2018, ES2019, ES2020, ES2021, ES2022, ESNext การเลือก target ที่เหมาะสมเป็นสิ่งสำคัญเพื่อให้แน่ใจว่าโค้ดสามารถทำงานร่วมกับสภาพแวดล้อมที่ต้องการได้ เช่น เบราว์เซอร์หรือ Node.js เวอร์ชันต่างๆ

ตัวอย่าง:

{
  "compilerOptions": {
    "target": "ES2020"
  }
}

module

ตัวเลือก module ใช้ระบุสไตล์การสร้างโค้ดโมดูล ค่าที่ใช้กันทั่วไปได้แก่ CommonJS, AMD, System, UMD, ES6 (ES2015), ES2020, และ ESNext การเลือกระบบโมดูลขึ้นอยู่กับสภาพแวดล้อมเป้าหมายและตัวรวมโมดูล (module bundler) ที่ใช้ (เช่น Webpack, Rollup, Parcel) สำหรับ Node.js มักใช้ CommonJS ในขณะที่แอปพลิเคชันเว็บสมัยใหม่นิยมใช้ ES6 หรือ ESNext ร่วมกับ module bundler การใช้ ESNext ช่วยให้นักพัฒนาสามารถใช้ประโยชน์จากฟีเจอร์และการปรับปรุงประสิทธิภาพล่าสุดได้ โดยอาศัย bundler ในการจัดการรูปแบบโมดูลสุดท้าย

ตัวอย่าง:

{
  "compilerOptions": {
    "module": "ESNext"
  }
}

lib

ตัวเลือก lib ใช้ระบุรายการของไฟล์ไลบรารีที่จะรวมอยู่ในการคอมไพล์ ไฟล์ไลบรารีเหล่านี้ให้คำจำกัดความของ type สำหรับ API ของ JavaScript ที่มีมาให้ในตัวและ API ของเบราว์เซอร์ ค่าที่ใช้กันทั่วไปได้แก่ ES5, ES6, ES2015, ES2016, ES2017, ES2018, ES2019, ES2020, ES2021, ES2022, ESNext, DOM, WebWorker, ScriptHost, ES2015.Core, ES2015.Collection, ES2015.Iterable, ES2015.Promise, ES2015.Proxy, ES2015.Reflect, ES2015.Generator, ES2015.Symbol, ES2015.Symbol.WellKnown, ES2016.Array.Include, ES2017.object, ES2017.Intl, ES2017.SharedMemory, ES2017.String, ES2017.TypedArrays, ES2018.Intl, ES2018.Promise, ES2018.RegExp, ES2019.Array, ES2019.Object, ES2019.String, ES2019.Symbol, ES2020.BigInt, ES2020.Promise, ES2020.String, ES2020.Symbol.WellKnown, ES2021.Promise, ES2021.String, ES2021.WeakRef, ES2022.Error, ES2022.Object, ES2022.String และอื่นๆ อีกมากมาย การเลือกไลบรารีที่เหมาะสมช่วยให้มั่นใจได้ว่าคอมไพเลอร์ TypeScript มีข้อมูล type ที่จำเป็นสำหรับสภาพแวดล้อมเป้าหมาย การใช้ไลบรารี DOM ช่วยให้โปรเจกต์สามารถคอมไพล์โค้ดที่ใช้ API เฉพาะของเบราว์เซอร์ได้โดยไม่มีข้อผิดพลาดเกี่ยวกับ type

ตัวอย่าง:

{
  "compilerOptions": {
    "lib": ["ES2020", "DOM"]
  }
}

allowJs

ตัวเลือก allowJs อนุญาตให้คอมไพเลอร์ TypeScript คอมไพล์ไฟล์ JavaScript ควบคู่ไปกับไฟล์ TypeScript ซึ่งมีประโยชน์สำหรับการย้ายโปรเจกต์ JavaScript ที่มีอยู่แล้วไปยัง TypeScript ทีละส่วน การตั้งค่านี้เป็น true จะทำให้คอมไพเลอร์สามารถประมวลผลไฟล์ .js ได้ ทำให้สามารถนำ TypeScript มาใช้ในโปรเจกต์ได้อย่างค่อยเป็นค่อยไป

ตัวอย่าง:

{
  "compilerOptions": {
    "allowJs": true
  }
}

jsx

ตัวเลือก jsx ใช้ระบุวิธีจัดการกับ синтаксис JSX ค่าที่ใช้กันทั่วไป ได้แก่ preserve, react, react-native, และ react-jsx โดย preserve จะคง синтаксис JSX ไว้ในผลลัพธ์ ในขณะที่ react จะแปลง JSX เป็นการเรียกใช้ React.createElement ส่วน react-jsx จะใช้การแปลง JSX แบบใหม่ที่เปิดตัวใน React 17 ซึ่งไม่จำเป็นต้อง import React เข้ามา การเลือกตัวเลือก JSX ที่ถูกต้องเป็นสิ่งสำคัญสำหรับโปรเจกต์ที่ใช้ React หรือไลบรารีอื่น ๆ ที่ใช้ JSX

ตัวอย่าง:

{
  "compilerOptions": {
    "jsx": "react-jsx"
  }
}

declaration

ตัวเลือก declaration จะสร้างไฟล์ประกาศ .d.ts ที่สอดคล้องกันสำหรับแต่ละไฟล์ TypeScript ไฟล์ประกาศเหล่านี้ประกอบด้วยข้อมูล type และถูกใช้โดยโปรเจกต์ TypeScript อื่นๆ เพื่อใช้งานโค้ดที่คอมไพล์แล้ว การสร้างไฟล์ประกาศเป็นสิ่งจำเป็นสำหรับการสร้างไลบรารีและโมดูลที่สามารถนำกลับมาใช้ใหม่ได้ ไฟล์เหล่านี้ช่วยให้โปรเจกต์ TypeScript อื่นๆ เข้าใจ types และ interfaces ที่ไลบรารีเปิดเผยออกมา โดยไม่จำเป็นต้องคอมไพล์ซอร์สโค้ดต้นฉบับ

ตัวอย่าง:

{
  "compilerOptions": {
    "declaration": true
  }
}

sourceMap

ตัวเลือก sourceMap จะสร้างไฟล์ source map ซึ่งทำหน้าที่จับคู่โค้ด JavaScript ที่สร้างขึ้นกลับไปยังโค้ด TypeScript ต้นฉบับ Source map มีความสำคัญอย่างยิ่งสำหรับการดีบักโค้ด TypeScript ในเบราว์เซอร์และสภาพแวดล้อมอื่นๆ เมื่อเกิดข้อผิดพลาดในโค้ด JavaScript, source map จะช่วยให้นักพัฒนาเห็นโค้ด TypeScript ที่สอดคล้องกันในดีบักเกอร์ ทำให้ง่ายต่อการระบุและแก้ไขปัญหา

ตัวอย่าง:

{
  "compilerOptions": {
    "sourceMap": true
  }
}

outDir

ตัวเลือก outDir ใช้ระบุไดเรกทอรีผลลัพธ์สำหรับไฟล์ JavaScript ที่สร้างขึ้น ตัวเลือกนี้ช่วยจัดระเบียบผลลัพธ์การบิลด์ของโปรเจกต์โดยการแยกซอร์สโค้ดออกจากโค้ดที่คอมไพล์แล้ว การใช้ outDir ทำให้การจัดการกระบวนการบิลด์และปรับใช้แอปพลิเคชันง่ายขึ้น

ตัวอย่าง:

{
  "compilerOptions": {
    "outDir": "dist"
  }
}

rootDir

ตัวเลือก rootDir ใช้ระบุไดเรกทอรีรากของโปรเจกต์ TypeScript คอมไพเลอร์จะใช้ไดเรกทอรีนี้เป็นฐานในการค้นหาชื่อโมดูล ตัวเลือกนี้มีความสำคัญอย่างยิ่งสำหรับโปรเจกต์ที่มีโครงสร้างไดเรกทอรีที่ซับซ้อน การตั้งค่า rootDir อย่างถูกต้องจะช่วยให้มั่นใจได้ว่าคอมไพเลอร์สามารถค้นหาโมดูลและส่วนที่ต้องพึ่งพาทั้งหมดที่จำเป็นได้

ตัวอย่าง:

{
  "compilerOptions": {
    "rootDir": "src"
  }
}

strict

ตัวเลือก strict จะเปิดใช้งานตัวเลือกการตรวจสอบ type ที่เข้มงวดทั้งหมด ขอแนะนำอย่างยิ่งสำหรับโปรเจกต์ TypeScript ใหม่ๆ เนื่องจากช่วยตรวจจับข้อผิดพลาดที่อาจเกิดขึ้นได้ตั้งแต่เนิ่นๆ ในกระบวนการพัฒนา การเปิดใช้งานโหมด strict จะบังคับใช้กฎการตรวจสอบ type ที่เข้มงวดขึ้น ส่งผลให้โค้ดมีความแข็งแกร่งและบำรุงรักษาง่ายขึ้น นับเป็นแนวทางปฏิบัติที่ดีที่สุดในการเปิดใช้งานโหมด strict ในโปรเจกต์ TypeScript ใหม่ทุกโปรเจกต์

ตัวอย่าง:

{
  "compilerOptions": {
    "strict": true
  }
}

esModuleInterop

ตัวเลือก esModuleInterop ช่วยให้สามารถทำงานร่วมกันระหว่างโมดูล CommonJS และ ES modules ได้ ซึ่งเป็นสิ่งสำคัญสำหรับโปรเจกต์ที่ใช้โมดูลทั้งสองประเภท เมื่อเปิดใช้งาน esModuleInterop, TypeScript จะจัดการความแตกต่างระหว่างโมดูล CommonJS และ ES modules โดยอัตโนมัติ ทำให้การ import และ export โมดูลระหว่างสองระบบง่ายขึ้น ตัวเลือกนี้มีประโยชน์อย่างยิ่งเมื่อทำงานกับไลบรารีของบุคคลที่สามที่อาจใช้ระบบโมดูลที่แตกต่างกัน

ตัวอย่าง:

{
  "compilerOptions": {
    "esModuleInterop": true
  }
}

moduleResolution

ตัวเลือก moduleResolution ระบุวิธีที่ TypeScript ค้นหาการ import โมดูล ค่าที่ใช้กันทั่วไปคือ Node และ Classic กลยุทธ์การค้นหาโมดูลแบบ Node เป็นค่าเริ่มต้นและอิงตามอัลกอริทึมการค้นหาโมดูลของ Node.js ส่วนกลยุทธ์การค้นหาโมดูลแบบ Classic นั้นเก่ากว่าและไม่ค่อยได้ใช้ การใช้กลยุทธ์การค้นหาโมดูลแบบ Node ช่วยให้มั่นใจได้ว่า TypeScript สามารถค้นหาการ import โมดูลได้อย่างถูกต้องในสภาพแวดล้อมของ Node.js

ตัวอย่าง:

{
  "compilerOptions": {
    "moduleResolution": "Node"
  }
}

baseUrl and paths

ตัวเลือก baseUrl และ paths ใช้เพื่อกำหนดค่าการค้นหาโมดูลสำหรับการ import โมดูลแบบไม่สัมพัทธ์ (non-relative) ตัวเลือก baseUrl ระบุไดเรกทอรีพื้นฐานสำหรับการค้นหาชื่อโมดูลที่ไม่ใช่แบบสัมพัทธ์ ส่วนตัวเลือก paths ช่วยให้คุณสามารถจับคู่ชื่อโมดูลไปยังตำแหน่งที่เฉพาะเจาะจงบนระบบไฟล์ได้ ตัวเลือกเหล่านี้มีประโยชน์อย่างยิ่งสำหรับโปรเจกต์ที่มีโครงสร้างไดเรกทอรีที่ซับซ้อนและเพื่อทำให้การ import โมดูลง่ายขึ้น การใช้ baseUrl และ paths สามารถทำให้โค้ดอ่านง่ายและบำรุงรักษาได้ง่ายขึ้น

ตัวอย่าง:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@components/*": ["src/components/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}

ตัวเลือก Include และ Exclude

ตัวเลือก include และ exclude ระบุว่าไฟล์ใดควรถูกรวมในการคอมไพล์และไฟล์ใดควรถูกยกเว้น ตัวเลือกเหล่านี้ใช้รูปแบบ glob เพื่อจับคู่ชื่อไฟล์ การใช้ include และ exclude ช่วยให้คุณควบคุมได้ว่าไฟล์ใดจะถูกประมวลผลโดยคอมไพเลอร์ TypeScript ซึ่งช่วยปรับปรุงประสิทธิภาพการบิลด์และลดข้อผิดพลาด เป็นแนวทางปฏิบัติที่ดีที่สุดที่จะระบุไฟล์ที่จะรวมในการคอมไพล์อย่างชัดเจน

ตัวอย่าง:

{
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

ตัวเลือก Extends

ตัวเลือก extends ช่วยให้คุณสามารถสืบทอดตัวเลือกคอมไพเลอร์จากไฟล์ tsconfig.json อื่นได้ ซึ่งมีประโยชน์สำหรับการแชร์การตั้งค่าทั่วไประหว่างหลายโปรเจกต์หรือสำหรับการสร้างการกำหนดค่าพื้นฐาน การใช้ตัวเลือก extends ส่งเสริมการใช้โค้ดซ้ำและลดความซ้ำซ้อน เป็นแนวทางปฏิบัติที่ดีที่สุดในการสร้างการกำหนดค่าพื้นฐานและขยายการใช้งานในแต่ละโปรเจกต์

ตัวอย่าง:

{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "jsx": "react-jsx"
  },
  "include": ["src/**/*"]
}

การกำหนดค่าขั้นสูง

นอกเหนือจากตัวเลือกคอมไพเลอร์ที่จำเป็นแล้ว tsconfig.json ยังสนับสนุนการกำหนดค่าขั้นสูงสำหรับสถานการณ์พิเศษอีกด้วย

การคอมไพล์แบบส่วนเพิ่ม (Incremental Compilation)

สำหรับโปรเจกต์ขนาดใหญ่ การคอมไพล์แบบส่วนเพิ่มสามารถปรับปรุงเวลาในการบิลด์ได้อย่างมาก TypeScript สามารถแคชผลลัพธ์ของการคอมไพล์ครั้งก่อนๆ และจะคอมไพล์เฉพาะไฟล์ที่มีการเปลี่ยนแปลงเท่านั้น การเปิดใช้งานการคอมไพล์แบบส่วนเพิ่มสามารถลดเวลาในการบิลด์สำหรับโปรเจกต์ขนาดใหญ่ได้อย่างมาก นี่เป็นสิ่งสำคัญอย่างยิ่งสำหรับโปรเจกต์ที่มีไฟล์และส่วนที่ต้องพึ่งพาจำนวนมาก

{
  "compilerOptions": {
    "incremental": true,
    "tsBuildInfoFile": ".tsbuildinfo"
  }
}

การอ้างอิงโปรเจกต์ (Project References)

การอ้างอิงโปรเจกต์ช่วยให้คุณสามารถจัดโครงสร้างโปรเจกต์ TypeScript ขนาดใหญ่เป็นโมดูลย่อยๆ ที่เป็นอิสระต่อกันได้ ซึ่งสามารถปรับปรุงเวลาในการบิลด์และการจัดระเบียบโค้ดได้ การใช้การอ้างอิงโปรเจกต์สามารถทำให้โปรเจกต์ขนาดใหญ่จัดการได้ง่ายขึ้นและบำรุงรักษาได้ง่ายขึ้น เป็นแนวทางปฏิบัติที่ดีที่สุดในการใช้การอ้างอิงโปรเจกต์สำหรับโปรเจกต์ขนาดใหญ่และซับซ้อน

{
  "compilerOptions": {
    "composite": true
  },
  "references": [
    { "path": "./module1" },
    { "path": "./module2" }
  ]
}

การกำหนด Type แบบกำหนดเอง

บางครั้งคุณอาจต้องให้คำจำกัดความของ type สำหรับไลบรารี JavaScript ที่ไม่มีมาให้ คุณสามารถสร้างไฟล์ .d.ts แบบกำหนดเองเพื่อกำหนด types สำหรับไลบรารีเหล่านี้ได้ การสร้างคำจำกัดความของ type แบบกำหนดเองช่วยให้คุณสามารถใช้ไลบรารี JavaScript ในโค้ด TypeScript ของคุณได้โดยไม่สูญเสียความปลอดภัยของ type ซึ่งมีประโยชน์อย่างยิ่งเมื่อทำงานกับโค้ด JavaScript แบบเก่าหรือไลบรารีที่ไม่มีคำจำกัดความของ type ของตัวเอง

// custom.d.ts
declare module 'my-library' {
  export function doSomething(x: number): string;
}

แนวทางปฏิบัติที่ดีที่สุด (Best Practices)

การแก้ไขปัญหาที่พบบ่อย

การกำหนดค่า tsconfig.json บางครั้งอาจเป็นเรื่องท้าทาย นี่คือปัญหาที่พบบ่อยและแนวทางแก้ไข:

ปัญหาการหาโมดูล (Module Resolution)

หากคุณพบข้อผิดพลาดในการค้นหาโมดูล ให้ตรวจสอบว่าตัวเลือก moduleResolution ได้รับการกำหนดค่าอย่างถูกต้อง และตัวเลือก baseUrl และ paths ได้รับการตั้งค่าอย่างเหมาะสม ตรวจสอบพาธที่ระบุในตัวเลือก paths อีกครั้งเพื่อให้แน่ใจว่าถูกต้อง และตรวจสอบว่าโมดูลที่จำเป็นทั้งหมดได้รับการติดตั้งในไดเรกทอรี node_modules

ข้อผิดพลาดเกี่ยวกับ Type (Type Errors)

ข้อผิดพลาดเกี่ยวกับ type สามารถเกิดขึ้นได้หากคำจำกัดความของ type ไม่ถูกต้องหรือขาดหายไป ตรวจสอบให้แน่ใจว่าคุณได้ติดตั้งคำจำกัดความของ type ที่ถูกต้องสำหรับไลบรารีทั้งหมดที่คุณใช้อยู่ หากคุณกำลังใช้ไลบรารี JavaScript ที่ไม่มีคำจำกัดความของ type ให้พิจารณาสร้างคำจำกัดความของ type แบบกำหนดเอง

ข้อผิดพลาดในการคอมไพล์ (Compilation Errors)

ข้อผิดพลาดในการคอมไพล์สามารถเกิดขึ้นได้หากมีข้อผิดพลาดทางไวยากรณ์หรือข้อผิดพลาดเกี่ยวกับ type ในโค้ด TypeScript ของคุณ ตรวจสอบข้อความแสดงข้อผิดพลาดอย่างละเอียดและแก้ไขข้อผิดพลาดทางไวยากรณ์หรือข้อผิดพลาดเกี่ยวกับ type ตรวจสอบให้แน่ใจว่าโค้ดของคุณเป็นไปตามแบบแผนการเขียนโค้ดของ TypeScript

สรุป

ไฟล์ tsconfig.json ที่กำหนดค่าไว้อย่างดีเป็นสิ่งจำเป็นสำหรับความสำเร็จของโปรเจกต์ TypeScript ด้วยความเข้าใจในตัวเลือกคอมไพเลอร์ที่จำเป็นและการกำหนดค่าขั้นสูง คุณจะสามารถเพิ่มประสิทธิภาพขั้นตอนการทำงานในการพัฒนา ปรับปรุงคุณภาพโค้ด และรับประกันความเข้ากันได้กับสภาพแวดล้อมเป้าหมายได้ การลงทุนเวลาในการกำหนดค่า tsconfig.json อย่างเหมาะสมจะให้ผลตอบแทนในระยะยาวโดยการลดข้อผิดพลาด ปรับปรุงการบำรุงรักษา และทำให้กระบวนการบิลด์มีประสิทธิภาพมากขึ้น ซึ่งส่งผลให้การพัฒนาซอฟต์แวร์มีประสิทธิภาพและเชื่อถือได้มากขึ้น ข้อมูลที่ให้ไว้ในที่นี้ออกแบบมาเพื่อให้สามารถนำไปใช้ได้ในระดับสากล และควรเป็นรากฐานที่มั่นคงในการเริ่มต้นโปรเจกต์ใหม่ด้วย TypeScript

อย่าลืมศึกษาเอกสารอย่างเป็นทางการของ TypeScript เพื่อดูข้อมูลล่าสุดและคำอธิบายโดยละเอียดของตัวเลือกคอมไพเลอร์ทั้งหมดที่มีให้ เอกสารของ TypeScript เป็นแหล่งข้อมูลที่มีค่าอย่างยิ่งในการทำความเข้าใจความซับซ้อนของการกำหนดค่า TypeScript