TypeScript กับ JavaScript: คู่มือแนะนำของคุณ
เผยแพร่แล้ว: 2022-03-11TypeScript หรือ JavaScript? นักพัฒนาซอฟต์แวร์พิจารณาตัวเลือกนี้สำหรับโปรเจ็กต์ Greenfield Web หรือ Node.js แต่ก็เป็นคำถามที่น่าพิจารณาสำหรับโปรเจ็กต์ที่มีอยู่ด้วยเช่นกัน ซูเปอร์เซ็ตของ JavaScript TypeScript นำเสนอคุณลักษณะทั้งหมดของ JavaScript บวกกับสิทธิพิเศษเพิ่มเติมบางประการ TypeScript กระตุ้นให้เราเขียนโค้ดอย่างหมดจด ทำให้โค้ดสามารถปรับขนาดได้มากขึ้น อย่างไรก็ตาม โครงการสามารถมี JavaScript ธรรมดาได้มากเท่าที่เราต้องการ ดังนั้นการใช้ TypeScript จึงไม่ใช่ข้อเสนอทั้งหมดหรือไม่มีเลย
ความสัมพันธ์ระหว่าง TypeScript และ JavaScript
TypeScript เพิ่มระบบประเภทที่ชัดเจนให้กับ JavaScript เพื่อให้สามารถบังคับใช้ประเภทตัวแปรได้อย่างเข้มงวด TypeScript เรียกใช้การตรวจสอบประเภทขณะ transpiling ซึ่งเป็นรูปแบบการคอมไพล์ที่แปลงโค้ด TypeScript เป็นโค้ด JavaScript ที่เว็บเบราว์เซอร์และ Node.js เข้าใจ
ตัวอย่าง TypeScript กับ JavaScript
เริ่มต้นด้วยข้อมูลโค้ด JavaScript ที่ถูกต้อง:
let var1 = "Hello"; var1 = 10; console.log(var1); ที่นี่ var1 เริ่มต้นด้วย string จากนั้นจึงกลายเป็น number
เนื่องจาก JavaScript มีการพิมพ์แบบหลวมๆ เท่านั้น เราจึงสามารถกำหนด var1 ใหม่เป็นตัวแปรประเภทใดก็ได้ ตั้งแต่สตริงไปจนถึงฟังก์ชันได้ตลอดเวลา
รันโค้ดนี้เอาท์พุต 10
ตอนนี้ มาเปลี่ยนรหัสนี้เป็น TypeScript:
let var1: string = "Hello"; var1 = 10; console.log(var1); ในกรณีนี้ เราประกาศ var1 เป็น string จากนั้นเราลองกำหนดตัวเลขให้กับมัน ซึ่งไม่ได้รับอนุญาตโดยระบบประเภทเข้มงวดของ TypeScript Transpiling ส่งผลให้เกิดข้อผิดพลาด:
TSError: ⨯ Unable to compile TypeScript: src/snippet1.ts:2:1 - error TS2322: Type 'number' is not assignable to type 'string'. 2 var1 = 10; หากเราต้องสั่งทรานสไพเลอร์ให้ปฏิบัติต่อข้อมูลโค้ด JavaScript ดั้งเดิมราวกับว่ามันเป็น TypeScript ทรานสปิลเลอร์จะอนุมานโดยอัตโนมัติว่า var1 ควรเป็น string | number string | number . นี่คือ TypeScript union type ซึ่งช่วยให้เราสามารถกำหนด var1 เป็น string หรือ number ได้ตลอดเวลา เมื่อแก้ไขข้อขัดแย้งของประเภทแล้ว โค้ด TypeScript ของเราจะทรานสไฟล์ได้สำเร็จ การดำเนินการจะสร้างผลลัพธ์เช่นเดียวกับตัวอย่าง JavaScript
TypeScript เทียบกับ JavaScript จาก 30,000 Feet: ความท้าทายในการขยายขนาด
JavaScript มีอยู่ทั่วไปทุกหนทุกแห่ง ขับเคลื่อนโปรเจ็กต์ทุกขนาด นำไปใช้ในรูปแบบที่ไม่เคยมีมาก่อนในช่วงวัยทารกในปี 1990 แม้ว่าจาวาสคริปต์จะเติบโตเต็มที่แล้ว แต่ก็ยังไม่เพียงพอเมื่อพูดถึงการรองรับความสามารถในการปรับขนาด ดังนั้น นักพัฒนาจึงต่อสู้กับแอปพลิเคชัน JavaScript ที่เติบโตขึ้นทั้งในด้านขนาดและความซับซ้อน
โชคดีที่ TypeScript ได้กล่าวถึงปัญหามากมายของการปรับขนาดโปรเจ็กต์ JavaScript เราจะเน้นที่ความท้าทายสามอันดับแรก: การตรวจสอบ การปรับโครงสร้างใหม่ และเอกสารประกอบ
การตรวจสอบความถูกต้อง
เราพึ่งพาสภาพแวดล้อมการพัฒนาแบบรวม (IDE) เพื่อช่วยในงานต่างๆ เช่น การเพิ่ม แก้ไข และทดสอบโค้ดใหม่ แต่ IDE ไม่สามารถตรวจสอบการอ้างอิง JavaScript ล้วนๆ ได้ เราลดข้อบกพร่องนี้โดยการตรวจสอบอย่างระมัดระวังในขณะที่เราเขียนโค้ดเพื่อป้องกันการพิมพ์ผิดในตัวแปรและชื่อฟังก์ชัน
ขนาดของปัญหาเพิ่มขึ้นแบบทวีคูณเมื่อโค้ดมีต้นกำเนิดมาจากบุคคลที่สาม ซึ่งการอ้างอิงที่เสียหายในสาขาโค้ดที่ดำเนินการไม่บ่อยอาจตรวจไม่พบได้ง่าย
ในทางตรงกันข้าม ด้วย TypeScript เราสามารถเน้นความพยายามของเราในการเขียนโค้ด โดยมั่นใจว่าข้อผิดพลาดใดๆ จะถูกระบุในเวลา transpile เพื่อแสดงสิ่งนี้ เรามาเริ่มด้วยโค้ด JavaScript แบบเดิม:
const moment = require('moment'); const printCurrentTime = (format) => { if (format === 'ISO'){ console.log("Current ISO TS:", moment().toISO()); } else { console.log("Current TS: ", moment().format(format)); } } การเรียก . .toISO() เป็นการสะกดผิดของวิธี moment.js toISOString() แต่โค้ดจะใช้งานได้ หากอาร์กิวเมนต์ format ไม่ใช่ ISO ครั้งแรกที่เราพยายามส่ง ISO ไปยังฟังก์ชัน จะทำให้เกิดข้อผิดพลาดรันไทม์: TypeError: moment(...).toISO is not a function
การค้นหารหัสที่สะกดผิดอาจเป็นเรื่องยาก codebase ปัจจุบันอาจไม่มีพาธไปยังบรรทัดที่เสีย ในกรณีนี้ การอ้างอิง .toISO() ที่ใช้งานไม่ได้ของเราจะไม่ถูกตรวจพบโดยการทดสอบ
หากเราพอร์ตรหัสนี้ไปที่ TypeScript IDE จะเน้นการอ้างอิงที่เสียหาย กระตุ้นให้เราทำการแก้ไข ถ้าเราไม่ทำอะไรเลยและพยายามที่จะ transpiler เราจะถูกบล็อก และ transpiler จะสร้างข้อผิดพลาดต่อไปนี้:
TSError: ⨯ Unable to compile TypeScript: src/catching-mistakes-at-compile-time.ts:5:49 - error TS2339: Property 'toISO' does not exist on type 'Moment'. 5 console.log("Current ISO TS:", moment().toISO());การปรับโครงสร้างใหม่
แม้ว่าการพิมพ์ผิดในการอ้างอิงโค้ดของบุคคลที่สามไม่ใช่เรื่องแปลก แต่ก็มีชุดปัญหาต่างๆ ที่เกี่ยวข้องกับการพิมพ์ผิดในข้อมูลอ้างอิงภายใน เช่น:
const myPhoneFunction = (opts) => { // ... if (opts.phoneNumbr) doStuff(); } นักพัฒนาเพียงรายเดียวสามารถค้นหาและแก้ไขอินสแตนซ์ของ phoneNumbr ให้จบลงได้อย่างง่ายดาย er
แต่ยิ่งทีมมีขนาดใหญ่เท่าใด ความผิดพลาดทั่วไปที่ธรรมดาและธรรมดานี้ยิ่งมีค่าใช้จ่ายสูงอย่างไม่สมเหตุสมผล ในระหว่างการปฏิบัติงาน เพื่อนร่วมงานจะต้องรับทราบและเผยแพร่การพิมพ์ผิดดังกล่าว อีกทางหนึ่ง การเพิ่มโค้ดเพื่อรองรับการสะกดทั้งสองแบบจะทำให้ codebase ขยายออกไปโดยไม่จำเป็น
ด้วย TypeScript เมื่อเราแก้ไขข้อผิดพลาด โค้ดที่ขึ้นต่อกันจะไม่ข้ามผ่านอีกต่อไป เป็นการส่งสัญญาณให้เพื่อนร่วมงานเผยแพร่การแก้ไขไปยังโค้ดของพวกเขา
เอกสาร
เอกสารที่ถูกต้องและเกี่ยวข้องเป็นกุญแจสำคัญในการสื่อสารภายในและระหว่างทีมนักพัฒนา นักพัฒนา JavaScript มักใช้ JSDoc เพื่อบันทึกวิธีการที่คาดหวังและประเภทคุณสมบัติ
คุณลักษณะภาษาของ TypeScript (เช่น คลาสนามธรรม อินเตอร์เฟส และคำจำกัดความของประเภท) ช่วยอำนวยความสะดวกในการเขียนโปรแกรมตามสัญญา ซึ่งนำไปสู่เอกสารที่มีคุณภาพ นอกจากนี้ การมีคำจำกัดความอย่างเป็นทางการของเมธอดและคุณสมบัติที่อ็อบเจ็กต์ต้องยึดถือจะช่วยระบุการเปลี่ยนแปลงที่แตกหัก สร้างการทดสอบ ดำเนินการตรวจสอบโค้ด และใช้รูปแบบสถาปัตยกรรม
สำหรับ TypeScript เครื่องมือพื้นฐาน TypeDoc (ตามข้อเสนอ TSDoc) จะดึงข้อมูลประเภท (เช่น คลาส อินเทอร์เฟซ เมธอด และคุณสมบัติ) ออกจากโค้ดของเราโดยอัตโนมัติ ดังนั้นเราจึงสร้างเอกสารที่ครอบคลุมมากกว่า JSDoc ได้อย่างง่ายดาย
ข้อดีของ TypeScript กับ JavaScript
ตอนนี้ มาสำรวจว่าเราจะใช้ TypeScript เพื่อจัดการกับความท้าทายด้านการปรับขยายเหล่านี้ได้อย่างไร
คำแนะนำโค้ดขั้นสูง/การปรับโครงสร้างใหม่
IDE จำนวนมากสามารถประมวลผลข้อมูลจากระบบประเภท TypeScript โดยให้การตรวจสอบความถูกต้องของข้อมูลอ้างอิงในขณะที่เราเขียนโค้ด ยิ่งไปกว่านั้น ขณะที่เราพิมพ์ IDE สามารถส่งเอกสารที่เกี่ยวข้องได้อย่างรวดเร็ว (เช่น อาร์กิวเมนต์ที่ฟังก์ชันคาดหวัง) สำหรับการอ้างอิงใดๆ และแนะนำชื่อตัวแปรที่ถูกต้องตามบริบท
ในข้อมูลโค้ด TypeScript นี้ IDE จะแนะนำการเติมข้อความอัตโนมัติของชื่อของคีย์ภายในค่าที่ส่งคืนของฟังก์ชัน:
/** * Simple function to parse a CSV containing people info. * @param data A string containing a CSV with 3 fields: name, surname, age. */ const parsePeopleData = (data: string) => { const people: {name: string, surname: string, age: number}[] = []; const errors: string[] = []; for (let row of data.split('\n')){ if (row.trim() === '') continue; const tokens = row.split(',').map(i => i.trim()).filter(i => i != ''); if (tokens.length < 3){ errors.push(`Row "${row}" contains only ${tokens.length} tokens. 3 required`); continue; } people.push({ name: tokens[0], surname: tokens[1], age: +tokens[2] }) } return {people, errors}; }; const exampleData = ` Gordon,Freeman,27 G,Man,99 Alyx,Vance,24 Invalid Row,, Again, Invalid `; const result = parsePeopleData(exampleData); console.log("Parsed People:"); console.log(result.people. map(p => `Name: ${p.name}\nSurname: ${p.surname}\nAge: ${p.age}`) .join('\n\n') ); if (result.errors.length > 0){ console.log("\nErrors:"); console.log(result.errors.join('\n')); }IDE ของฉัน รหัส Visual Studio ให้คำแนะนำนี้ (ในคำบรรยาย) เมื่อฉันเริ่มเรียกใช้ฟังก์ชัน (บรรทัดที่ 31):
ยิ่งไปกว่านั้น คำแนะนำการเติมข้อความอัตโนมัติของ IDE (ในคำบรรยาย) นั้นถูกต้องตามบริบท โดยแสดงเฉพาะชื่อที่ถูกต้องภายในสถานการณ์คีย์ที่ซ้อนกัน (บรรทัดที่ 34):
คำแนะนำแบบเรียลไทม์ดังกล่าวนำไปสู่การเข้ารหัสที่รวดเร็วยิ่งขึ้น ยิ่งไปกว่านั้น IDE สามารถพึ่งพาข้อมูลประเภทที่เข้มงวดของ TypeScript เพื่อปรับโครงสร้างโค้ดใหม่ในทุกขนาด การดำเนินการต่างๆ เช่น การเปลี่ยนชื่อคุณสมบัติ การเปลี่ยนตำแหน่งไฟล์ หรือแม้แต่การแยก superclass จะกลายเป็นเรื่องเล็กน้อยเมื่อเรามั่นใจ 100% ในความถูกต้องของข้อมูลอ้างอิงของเรา

รองรับอินเทอร์เฟซ
ตรงกันข้ามกับ JavaScript TypeScript ให้ความสามารถในการกำหนดประเภทโดยใช้ อินเทอร์เฟซ อินเทอร์เฟซแสดงรายการอย่างเป็นทางการ—แต่ไม่ได้ใช้งาน—เมธอดและคุณสมบัติที่อ็อบเจ็กต์ต้องมี โครงสร้างภาษานี้มีประโยชน์อย่างยิ่งสำหรับการทำงานร่วมกันกับนักพัฒนารายอื่น
ตัวอย่างต่อไปนี้เน้นวิธีที่เราสามารถใช้ประโยชน์จากคุณลักษณะของ TypeScript เพื่อนำรูปแบบ OOP ทั่วไปไปใช้อย่างเรียบร้อย ในกรณีนี้ กลยุทธ์ และ สายความรับผิดชอบ จึงเป็นการปรับปรุงตัวอย่างก่อนหน้านี้:
export class PersonInfo { constructor( public name: string, public surname: string, public age: number ){} } export interface ParserStrategy{ /** * Parse a line if able. * @returns The parsed line or null if the format is not recognized. */ (line: string): PersonInfo | null; } export class PersonInfoParser{ public strategies: ParserStrategy[] = []; parse(data: string){ const people: PersonInfo[] = []; const errors: string[] = []; for (let row of data.split('\n')){ if (row.trim() === '') continue; let parsed; for (let s of this.strategies){ parsed = s(row); if (parsed) break; } if (!parsed){ errors.push(`Unable to find a strategy capable of parsing "${row}"`); } else { people.push(parsed); } } return {people, errors}; } } const exampleData = ` Gordon,Freeman,27 G;Man;99 {"name":"Alyx", "surname":"Vance", "age":24} Invalid Row,, Again, Invalid `; const parser = new PersonInfoParser(); const createCSVStrategy = (fieldSeparator = ','): ParserStrategy => (line) => { const tokens = line.split(fieldSeparator).map(i => i.trim()).filter(i => i != ''); if (tokens.length < 3) return null; return new PersonInfo(tokens[0], tokens[1], +tokens[2]); }; parser.strategies.push( (line) => { try { const {name, surname, age} = JSON.parse(line); return new PersonInfo(name, surname, age); } catch(err){ return null; } }, createCSVStrategy(), createCSVStrategy(';') ); const result = parser.parse(exampleData); console.log("Parsed People:"); console.log(result.people. map(p => `Name: ${p.name}\nSurname: ${p.surname}\nAge: ${p.age}`) .join('\n\n') ); if (result.errors.length > 0){ console.log("\nErrors:"); console.log(result.errors.join('\n')); }โมดูล ES6—ทุกที่
ในขณะที่เขียนนี้ รันไทม์ JavaScript ของ front-end และ back-end บางตัวไม่รองรับโมดูล ES6 อย่างไรก็ตาม ด้วย TypeScript เราสามารถใช้ไวยากรณ์โมดูล ES6 ได้:
import * as _ from 'lodash'; export const exampleFn = () => console.log(_.reverse(['a', 'b', 'c'])); เอาต์พุต transpiled จะเข้ากันได้กับสภาพแวดล้อมที่เราเลือก ตัวอย่างเช่น การใช้ตัวเลือกคอมไพเลอร์ --module CommonJS เราได้รับ:
"use strict"; exports.__esModule = true; exports.exampleFn = void 0; var _ = require("lodash"); var exampleFn = function () { return console.log(_.reverse(['a', 'b', 'c'])); }; exports.exampleFn = exampleFn; การใช้ --module UMD แทน TypeScript จะแสดงรูปแบบ UMD ที่ละเอียดยิ่งขึ้น:
(function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "lodash"], factory); } })(function (require, exports) { "use strict"; exports.__esModule = true; exports.exampleFn = void 0; var _ = require("lodash"); var exampleFn = function () { return console.log(_.reverse(['a', 'b', 'c'])); }; exports.exampleFn = exampleFn; });คลาส ES6—ทุกที่
สภาพแวดล้อมแบบเดิมมักไม่รองรับคลาส ES6 ทรานสไพล์ TypeScript ช่วยให้มั่นใจได้ถึงความเข้ากันได้โดยใช้โครงสร้างเฉพาะเป้าหมาย นี่คือข้อมูลโค้ดแหล่งที่มาของ TypeScript:
export class TestClass { hello = 'World'; }เอาต์พุต JavaScript ขึ้นอยู่กับทั้งโมดูลและเป้าหมาย ซึ่ง TypeScript ให้เราระบุได้
นี่คือสิ่งที่ --module CommonJS --target es3 ให้ผลตอบแทน:
"use strict"; exports.__esModule = true; exports.TestClass = void 0; var TestClass = /** @class */ (function () { function TestClass() { this.hello = 'World'; } return TestClass; }()); exports.TestClass = TestClass; การใช้ --module CommonJS --target es6 แทน เราจะได้ผลลัพธ์ transpiled ต่อไปนี้ คีย์เวิร์ด class ใช้เพื่อกำหนดเป้าหมาย ES6:
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TestClass = void 0; class TestClass { constructor() { this.hello = 'World'; } } exports.TestClass = TestClass;ฟังก์ชัน Async/Await—ทุกที่
Async/await ทำให้โค้ด JavaScript แบบอะซิงโครนัสง่ายต่อการเข้าใจและบำรุงรักษา TypeScript นำเสนอฟังก์ชันนี้ให้กับรันไทม์ทั้งหมด แม้กระทั่งกับรันไทม์ที่ไม่ได้ให้ async/await โดยกำเนิด
โปรดทราบว่าในการรัน async/await บนรันไทม์รุ่นเก่า เช่น ES3 และ ES5 คุณจะต้องได้รับการสนับสนุนภายนอกสำหรับเอาต์พุตแบบ Promise (เช่น ผ่าน Bluebird หรือ ES2015 polyfill) Promise polyfill ที่มาพร้อมกับ TypeScript จะผสานรวมเข้ากับเอาต์พุต transpiled ได้อย่างง่ายดาย—เราเพียงแค่ต้องกำหนดค่าตัวเลือกคอมไพเลอร์ lib ให้สอดคล้องกัน
รองรับฟิลด์คลาสส่วนตัว—ทุกที่
แม้แต่สำหรับเป้าหมายดั้งเดิม TypeScript รองรับฟิลด์ private ในลักษณะเดียวกับภาษาที่พิมพ์อย่างมาก (เช่น Java หรือ C#) ในทางตรงกันข้าม รันไทม์ JavaScript จำนวนมากสนับสนุนฟิลด์ private ผ่านไวยากรณ์คำนำหน้าแฮช ซึ่งเป็นข้อเสนอที่เสร็จสิ้นแล้วของ ES2022
ข้อเสียของ TypeScript กับ JavaScript
ตอนนี้เราได้เน้นถึงประโยชน์หลักของการใช้ TypeScript แล้ว เรามาสำรวจสถานการณ์ที่ TypeScript อาจไม่เหมาะกัน
Transpilation: ศักยภาพสำหรับความไม่ลงรอยกันของเวิร์กโฟลว์
เวิร์กโฟลว์เฉพาะหรือข้อกำหนดของโปรเจ็กต์อาจเข้ากันไม่ได้กับขั้นตอนการทรานสพิลของ TypeScript: ตัวอย่างเช่น หากเราต้องการใช้เครื่องมือภายนอกเพื่อเปลี่ยนโค้ดหลังจากการปรับใช้ หรือหากเอาต์พุตที่สร้างขึ้นต้องเป็นมิตรกับนักพัฒนา
ตัวอย่างเช่น ฉันเพิ่งเขียนฟังก์ชัน AWS Lambda สำหรับสภาพแวดล้อม Node.js TypeScript นั้นไม่เหมาะสมเพราะการต้องถอดเสียงจะทำให้ฉันและสมาชิกในทีมคนอื่นๆ ไม่สามารถแก้ไขฟังก์ชันโดยใช้ตัวแก้ไขออนไลน์ของ AWS นี่เป็นตัวแบ่งข้อตกลงสำหรับผู้จัดการโครงการ
ระบบประเภทใช้งานได้จนกว่าจะถึงเวลาเปลี่ยนผ่าน
เอาต์พุต JavaScript ของ TypeScript ไม่มีข้อมูลประเภท ดังนั้นจึงไม่ทำการตรวจสอบประเภท ดังนั้นความปลอดภัยของประเภทจึงอาจหยุดทำงานขณะใช้งานจริง ตัวอย่างเช่น สมมติว่าฟังก์ชันถูกกำหนดให้ส่งคืนอ็อบเจ็กต์เสมอ หากคืน null จากการใช้งานภายในไฟล์ . .js ข้อผิดพลาดรันไทม์จะเกิดขึ้น
พิมพ์คุณลักษณะที่ขึ้นกับข้อมูล (เช่น ฟิลด์ส่วนตัว อินเทอร์เฟซ หรือข้อมูลทั่วไป) เพิ่มมูลค่าให้กับโครงการใดๆ แต่จะถูกคัดลอกออกไปในขณะที่กำลังถ่ายโอน ตัวอย่างเช่น สมาชิกชั้นเรียน private จะไม่เป็นแบบส่วนตัวอีกต่อไปหลังจากการถ่ายทอด เพื่อความชัดเจน ปัญหารันไทม์ในลักษณะนี้ไม่ใช่เฉพาะ TypeScript และคุณสามารถคาดหวังว่าจะพบกับปัญหาเดียวกันกับ JavaScript ด้วย
การรวม TypeScript และ JavaScript
แม้ว่า TypeScript จะมีประโยชน์มากมาย แต่บางครั้งเราไม่สามารถปรับการแปลงโปรเจ็กต์ JavaScript ทั้งหมดในคราวเดียวได้ โชคดีที่เราสามารถระบุ Transpiler ของ TypeScript—แบบไฟล์ต่อไฟล์—สิ่งที่จะตีความว่าเป็น JavaScript ธรรมดา อันที่จริง วิธีการแบบผสมนี้สามารถช่วยลดความท้าทายส่วนบุคคลที่เกิดขึ้นตลอดวงจรชีวิตของโครงการ
เราอาจต้องการให้ JavaScript ไม่เปลี่ยนแปลงหากรหัส:
- ถูกเขียนขึ้นโดยอดีตเพื่อนร่วมงานและต้องใช้ความพยายามอย่างมากในด้านวิศวกรรมย้อนกลับเพื่อแปลงเป็น TypeScript
- ใช้เทคนิคที่ไม่ได้รับอนุญาตใน TypeScript (เช่น เพิ่มคุณสมบัติหลังการสร้างอินสแตนซ์ของวัตถุ) และจะต้องมีการปรับโครงสร้างใหม่เพื่อให้เป็นไปตามกฎของ TypeScript
- อยู่ในทีมอื่นที่ยังคงใช้ JavaScript ต่อไป
ในกรณีเช่นนี้ ไฟล์ การประกาศ (ไฟล์ .d.ts ซึ่งบางครั้งเรียกว่าไฟล์คำจำกัดความหรือไฟล์การพิมพ์) ให้ข้อมูลประเภทที่เพียงพอสำหรับ TypeScript เพื่อเปิดใช้งานคำแนะนำ IDE ในขณะที่ปล่อยโค้ด JavaScript ไว้ตามที่เป็นอยู่
ไลบรารี JavaScript จำนวนมาก (เช่น Lodash, Jest และ React) ให้ไฟล์การพิมพ์ TypeScript ในแพ็คเกจแยกประเภท ในขณะที่อื่นๆ (เช่น Moment.js, Axios และ Luxon) รวมไฟล์การพิมพ์ไว้ในแพ็คเกจหลัก
TypeScript กับ JavaScript: คำถามของการทำให้เพรียวลมและความสามารถในการปรับขนาด
การสนับสนุน ความยืดหยุ่น และการปรับปรุงที่ไม่มีใครเทียบได้ผ่าน TypeScript ช่วยปรับปรุงประสบการณ์ของนักพัฒนาอย่างมาก ทำให้โครงการและทีมสามารถปรับขนาดได้ ต้นทุนหลักในการรวม TypeScript เข้ากับโปรเจ็กต์คือการเพิ่มขั้นตอนการสร้าง transpilation สำหรับแอปพลิเคชันส่วนใหญ่ การทรานสไพล์เป็น JavaScript ไม่เป็นปัญหา แทนที่จะเป็นก้าวย่างไปสู่ประโยชน์มากมายของ TypeScript
อ่านเพิ่มเติมในบล็อก Toptal Engineering:
- การทำงานกับ TypeScript และ Jest Support: บทช่วยสอน AWS SAM
