Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Lookback TypeScript ESM support and what should...

Avatar for Saji Saji
May 24, 2025
110

Lookback TypeScript ESM support and what should we do now.

Avatar for Saji

Saji

May 24, 2025
Tweet

Transcript

  1. ͜ͷεϥΠυͰ࢖͏༻ޠʹ͍ͭͯ /BUJWF&4. w /PEFKT΍ϒϥ΢βͰ&4.Λ௚઀ධՁɺղܾ͢Δํࣜɺ͓ΑͼͦͷϑΝΠϧ w ٖࣅ&4.ͱൺֱͯ͠ʮ/BUJWFʯ ٖࣅ&4. 'BVY&4.'BLF&4.  w

    $+4΁ม׵͢Δ͜ͱΛલఏʹॻ͔Εͨ&4.ͷܗࣜɾϑΝΠϧ w &4.ͷه๏ʹ४ڌ͢Δ͕ɺ/BUJWF&4.ͱ͸ඍົʹϧʔϧ͕ҧͬͨΓ͢Δ w ֦ுࢠলུ͢Δ͠ͳ͍ͱ͔
  2. ෮श $+4ͷه๏ *NQPSU &YQPSU ಛ௃$+4͸ಉظͳղܾɾ֦ுࢠΛলུͰ͖Δ const module = require("./module"); //

    module શମ const { funcA, funcB } = require("./module"); // ෳ਺import module.exports = func; // 1ͭͷModule exports.funcA = ()=>{…} // named export
  3. ෮श &4.ͷه๏ *NQPSU  &YQPSU ಛ௃&4.Ͱ͸ඇಉظͳղܾɾ/BUJWF&4.Ͱ͸֦ுࢠΛলུͰ͖ͳ͍ import module from "./module.js";

    // default import import { funcA } from "./module.js"; // named import export default function() {...}; // default export export const funcA = ()=> {...}; // named export
  4. &4.ͱ$+4ͷྺ࢙ ௒؆қ൛ w $PNNPO+4͕ఏҊ͞ΕɺͦͷϞδϡʔϧγεςϜΛ/PEFKT͕࠾༻   w ͦͷޙ/PEFKTฒͼʹपลΤίγεςϜ͕ීٴ XFC։ൃͷσϑΝΫτ΁ 

    w 54΋͜ͷࠒ஀ੜ🎉   w &$."4DSJQU͕೥ʹݴޠඪ४ͱͯ͠ϞδϡʔϧγεςϜΛࡦఆ&4. w ֤SVOUJNF͕&4.ͷ࣮ߦΛTVQQPSU w /PEF KTW  ओཁϒϥ΢β ೥͝Ζ  w ͔͢͠͠Ͱʹ$+4ʹΑͬͯங͔Εͨࢿ࢈͸େ͖͘ɺ&4.Ҡߦ͸ঃʑʹਐΉ
  5. /PEFͷ&4.αϙʔτ /PEF KT͕&4.ͷ࣮ߦΛαϙʔτͨ͠ W  w ैདྷͷ$+4ʹՃ͑ͯ/BUJWF&4.ͳϑΝΠϧ΋࣮ߦͰ͖ΔΑ͏ʹ ৽͍֦͠ுࢠ.cjsͱ.mjs w .cjs໌ࣔతʹ$+4ͩͱએݴͰ͖Δ

    w .mjs໌ࣔతʹ&4.ͩͱએݴͰ͖Δ &4.ͩͱͲ͏΍ͬͯݟ෼͚Δ͔ʁ w ֦ுࢠͰ໌ࣔతʹΘ͔Δ͔ʁˠQBDLBHFKTPOͷtypeˠ$+4
  6. 54ͷ&4.ରԠؔ࿈͢ΔΦϓγϣϯ moduleResolutionར༻͢ΔϞδϡʔϧղܾΞϧΰϦζϜͷϞσϧ w ΋ͷʹΑͬͯ͸NPEVMFΦϓγϣϯʹΑͬͯڧ੍͞ΕΔ moduleΦϓγϣϯ͕OPEFܥͷ৔߹ w module: "node16"PS"node18"ˠmoduleResolution: "node16" w

    module: "nodenext"ˠmoduleResolution: "nodenext" w ࠓͷॴ"node16""nodenext" ʹࠩ෼͸ͳ͍ w node16͸ݻఆ͞Ε͍ͯΔ͕ɺnodenext͸ಈతʹมߋ͞ΕΔՄೳੑ͋Γ
  7. UT֦ுΛ͚ͭΔ͜ͱʹର͢Δ̏͘͢Έ໰୊ Կ͔ΛऔΖ͏ͱ͢ΔͱԿ͔Λࣺͯͳ͍ͱ͍͚ͳ͍😭 w ૉ௚ʹ KTͰ͔͘ w ˠ❌/PEFͰ54Λ௚઀࣮ߦͰ͖ͳ͍ w --allowImportingTsExtensions༗ޮ w

    ˠ❌+4ʹॻ͖ग़͢͜ͱ͸Ͱ͖ͳ͍ ܕఆٛϑΝΠϧ΋  w --rewriteRelativeImportExtensions༗ޮ w ˠ❌ಈతʹJNQPSUTVCQBUIJNQPSU͸࢖͑ͳ͍
  8. #SPXTFSΞϓϦέʔγϣϯίʔυͷઃఆ ඞਢ w "moduleResolution" : "bundler"ʹ͢Δͷ͕؊ w "module" : "bundler"ͷ৔߹"preserve"͔"esnext"͔͠બ΂ͳ͍

    ৔߹ʹΑͬͯඞཁͰ͖ͨΒ w "allowImportingTsExtensions"֦ுࢠΛলུͤͣ.tsͰJNQPSU w "allowArbitraryExtensions"ඇ+BWB4DSJQUϑΝΠϧΛJNQPSU͢Δ
  9. #SPXTFSΞϓϦέʔγϣϯίʔυͷઃఆྫ "compilerOptions": { // must "moduleResolution": "bundler", "module": "preserve", //

    or `"esnext"` // optional / recommended "noEmit": true, // or `emitDeclarationOnly` "allowImportingTsExtensions": true, "allowArbitraryExtensions": true, "verbatimModuleSyntax": true } // package.json { type : "module" }
  10. /PEFΞϓϦέʔγϣϯίʔυͷઃఆ ඞਢ w "module" :"nodenext" "node16" / "node18" Λબ୒ w

    "moduleResolution"ˢͰࣗಈతʹܾఆ͞ΕΔͷͰུ Ͱ͖ͨΒ w "verbatimModuleSyntax"'VMM/BUJWF&4.ͳΒ
  11. /PEFKTΞϓϦέʔγϣϯίʔυͷઃఆྫ "compilerOptions": { // must "module": "nodenext", // recommended "verbatimModuleSyntax":

    true, // TS௚઀࣮ߦ͍ͨ͠ & jsͱܕఆٛϑΝΠϧ΋ు͖͍ͨ "rewriteRelativeImportExtensions": true } // package.json { type : "module" }
  12. /PEFKTΞϓϦέʔγϣϯίʔυͷઃఆྫ "compilerOptions": { // must "module": "nodenext", // recommended "verbatimModuleSyntax":

    true, // js / .d.ts ు͔ͳ͍͍ͯ͘ਓ(TS௚઀࣮ߦ͚ͩ) "allowImportingTsExtensions": true "noEmit": true } // package.json { type : "module" }
  13. &4.͚ͩ͡ΌμϝͰ͔͢ʁ 1VSF&4.ύοέʔδ &4.͔͠ग़ྗ͍ͯ͠ͳ͍ Ͱग़͢༐ؾ w ݹ͍/PEF͡Όͳ͚Ε͹&4.αϙʔτͯ͠Δ w #VOEMFલఏͰϞμϯͳόϯυϥ࢖ͬͯΔͳΒ&4.͚ͩͰ͍͍ w ΄Μͱʹ$+4Ͱಡ·ΕΔͷ͔ʁ

    w ࣾ಺ར༻͚ͩͱ͔ͳΒಡΉଆΛ௚ͤ͹໰୊ͳ͍͜ͱ΋ w require(ESM)ͷ͓͔͛Ͱ੍ݶ͸͋ΕͲޓ׵ੑ΋޲্ͨ͠ w 1VSF&4.ʹͳͬͨ༗໊ϥΠϒϥϦ΋ଟ͍
  14. &4.ʹॻ͖ग़࣌͢ͷઃఆ ඞਢ w "module" : OPEFҎ্ͳΒ "nodenext" w "declaration"ܕఆٛϑΝΠϧ͸ͪΌΜͱग़ྗ Ͱ͖ͨΒ

    w "verbatimModuleSyntax"UZQFJNQPSUΛڧ੍͢ΔͷͰɺՄೳͳΒ ΍ΊΔ w "paths"5ZQF4DSJQUͷܕղܾͱSVOUJNFڍಈ͕มΘΔՄೳੑ
  15. /PEFKTϥΠϒϦίʔυͷઃఆྫ "compilerOptions": { // must "module": "nodenext", "declaration" : true

    // recommended "verbatimModuleSyntax": true, } // package.json { type : "module" }
  16. &4.෩ 'BVY&4. Ͱॻ͍ͨࢿ࢈͕େ͖͍ํ ϥΠϒϥϦͷ৔߹PS/PEFͰಈ͘ΞϓϦͷ৔߹ w ૣΊͷ&4.ҠߦΛࢹ໺ʹೖΕ͍ͨ 0QJOJPO  w Ͱͳ͍ͱ1VSF&4.ύοέʔδ࢖͏ͷ΋&4.ͱͯ͠ॻ͖ग़͢ͷ΋໘౗

    #VOEMF͢ΔΞϓϦίʔυͷ৔߹ w "moduleResolution": "bundler"͓͚ͯ͠͹Ұ୴ͦͷ··Ͱ΋ಈ͘ w ͱ͸͍͑༨༟͕͋ΔͷͰ͋Ε͹Ҡߦ͍͚ͨ͠Ͳ 0QJOJPO
  17. ࢀߟʹ͍͍ͤͯͨͩͨ͞هࣄɾϦιʔε w 5ZQF4DSJQU%PDVNFOUBUJPO.PEVMFT$IPPTJOH$PNQJMFS0QUJPOT w 5ZQF4DSJQU%PDVNFOUBUJPO.PEVMFT&4.$+4*OUFSPQFSBCJMJUZ w 5ZQF4DSJQU%PDVNFOUBUJPO.PEVMFT3FGFSFODF w 5ZQF4DSJQU%PDVNFOUBUJPO.PEVMFT5IFPSZ w

    5ZQF4DSJQU%PDVNFOUBUJPO5ZQF4DSJQU w 5ZQF4DSJQU%PDVNFOUBUJPO5ZQF4DSJQU w BSFUIFUZQFTXSPOHBSFUIFUZQFTXSPOHHJUIVCJPu(JU)VC w 54ͷSFXSJUF3FMBUJWF*NQPSU&YUFOTJPOTΦϓγϣϯΛ࢖͏લʹಡΉهࣄ w 5ZQF4DSJQUҎ߱Ͱ&4.ରԠ͸Ͳ͏ͳΔͷ͔ʁ w 5ZQF4DSJQUͰ௥Ճ͞ΕͨWFSCBUJN.PEVMF4ZOUBYͱ͸Կ͔ʁ
  18. ࢀߟʹ͍͍ͤͯͨͩͨ͞هࣄɾϦιʔε w 5ZQF4DSJQUº/PEFKTͰ&$."4DSJQU.PEVMFTΛࢼ͢$-07&3🍀 w 5ZQF4DSJQUͷNPEVMFΦϓγϣϯͷ࿩ɺ͋Δ͍͸5ZQF4DSJQU։ൃऀͷۤ೰ɺ͋Δ͍͸$+4ͱ&4.ͷ࿩ w 5ZQF4DSJQU͕౰ͨΓલʯʹͳͬͨੈքʹ͓͍ͯɺ&4Ϟδϡʔϧຊདྷͷӡ༻ʹඞཁͳߟ͑ํͱઃఆͱ͸ w /PEFKT 5ZQF4DSJQUͷϞδϡʔϧΛ੔ཧͯ͠ΈΔ

    w /PEFKT/BUJWF&4.΁ͷಓʙ࠷ऴষ#BCFM5ZQF4DSJQU.PEVMFTͱͷಆ͍ʙc115 w ࣮ફ/PEFKT/BUJWF&4.Š8BOUFEMZͰͷΞϓϦέʔγϣϯҠߦࣄྫc8BOUFEMZ&OHJOFFS#MPH w SFRVJSF FTN JO/PEFKTc+PZFF$IFVOHT#MPH w .PWFPOUP&4.POMZ w %VBM1BDLBHF)B[BSEGSPNTDSBUDI
  19. ෇࿥%VBM1BDLBHFͰؤுΔ৔߹ ඇਪ঑ جຊํ਑ w QBDLBHFKTPO͸ڞ௨ͳͷͰUZQFNPEVMFͰ&4.Ͱίʔυ͸ॻ͘ w &4.ɾ$+4༻ʹͦΕͧΕUTDPO fi HΛ࡞Δ w

    ˠग़ྗઌΛ෼͚͓ͯ͘ w QBDLBHFKTPOͷ$POEJUJPOBMFYQPSUTػೳΛ࢖͏ w %VBM1BDLBHFʹΑΔ໰୊͸ೝ͓ࣝͯ͘͠ ໨ΛᛉΕΔ͜ͱΛ֬ೝ
  20. ෇࿥%VBM1BDLBHFͰؤுΔ৔߹ͷઃఆ // tsconfig.esm.json "compilerOptions": { "module": "nodenext", // or "node16"

    / "node18" // ... } // tsconfig.cjs.json "compilerOptions": { "module": "commojs", "esModuleInterop": true, // ... }
  21. ෇࿥%VBM1BDLBHFͰؤுΔ৔߹ 54͔Β͸FYQPSTͷUZQFTEFGBVMUϑΟʔϧυ΋ղऍ͢ΔΑ͏ʹͳͬͨ "exports": { ".": { "import": { // for

    ESM "types": "./types/esm/index.d.ts", // types "default": "./esm/index.js" // js }, "require": {...} } }
  22. ෇࿥%VBM1BDLBHFͰؤுΔ৔߹ Ճ͑ͯݹ͍/PEF΍54ͷͨΊʹ'BMMCBDL΋ࢦఆ͓ͯ͘͠ͱྑ͍ { // Fall-back for older versions of TypeScript

    "types": "./types/index.d.ts", // CJS fall-back for older versions of Node.js "main": "./commonjs/index.cjs" }