ഒരു TypeScript monorepo-യിൽ രണ്ട് വരിയുടെ ഒരു bugfix പൾഷ് ചെയ്യുമ്പോൾ, പത്ത് മിനിറ്റ് നീളുന്ന type checking-നായി നിങ്ങളുടെ build pipeline കാത്തുനിൽക്കേണ്ടി വന്നിട്ടുണ്ടെങ്കിൽ, നിങ്ങൾക്ക് ഈ പ്രശ്നം മനസ്സിലാകും. ഈ താമസം bundling കൊണ്ടോ minification കൊണ്ടോ അല്ല. അത് TypeScript നിങ്ങളുടെ declaration files എഴുതാൻ ശ്രമിക്കുന്ന സമയത്താണ് സംഭവിക്കുന്നത്. ഒരു .d.ts ഫയൽ പോലും പുറത്തിറക്കുന്നതിന് മുമ്പ്, കംപൈലർ പൂർണ്ണമായ type graph പരിഹരിക്കേണ്ടതുണ്ട്. അത് imports പരിശോധിക്കുന്നു, generics വിലയിരുത്തുന്നു, കൂടാതെ മൂന്ന് dependency layers ആഴത്തിലുള്ളേക്കാവുന്ന return types എന്നിവ കണ്ടെത്തുന്നു. നിങ്ങൾ മാറ്റം വരുത്തിയ ഒരു ഫയൽ മറ്റൊരു ഫയലിനെ സ്പർശിക്കുന്നു, അത് മൂന്നാമതൊന്നിനെ സ്പർശിക്കുന്നു, പെട്ടെന്ന് നിങ്ങളുടെ ഫങ്ക്ഷൻ എന്ത് റിട്ടേൺ ചെയ്യുന്നു എന്ന് വിവരിക്കാൻ വേണ്ടി കംപൈലർ മുഴുവൻ റെപ്പോസിറ്ററിയിലും അന്വേഷണം നടത്തുന്നു.

ആ ശീലം മാറ്റുന്നതിനായി TypeScript 6.0 isolatedDeclarations അവതരിപ്പിക്കുന്നു.

യഥാർത്ഥ തടസ്സം

Declaration files നിങ്ങളുടെ കോഡിന്റെ പബ്ലിക് കോൺട്രാക്റ്റുകളാണ് (public contract). മറ്റൊരു ഡെവലപ്പർ നിങ്ങളുടെ പാക്കേജ് ഇംപോർട്ട് ചെയ്യുമ്പോൾ, TypeScript സോഴ്സ് കോഡിന് പകരം .d.ts ഫയലുകളാണ് വായിക്കുന്നത്. ആ ഫയലുകൾ കൃത്യമായി നിർമ്മിക്കുക എന്നതിനർത്ഥം കംപൈലറിന് type checker ഒഴിവാക്കാൻ കഴിയില്ല എന്നാണ്. ഒരു ഔട്ട്പുട്ട് വരി പോലും എഴുതുന്നതിന് മുമ്പ് ഓരോ ഷേപ്പും (shape), ഓരോ യൂണിയനും (union), ഓരോ ഇൻഫേർഡ് റിട്ടേൺ ടൈപ്പും (inferred return type) കംപൈലർ അറിയണം.

അൻപത് ഫയലുകളുള്ള ഒരു ചെറിയ പ്രോജക്റ്റിൽ ഇത് പെട്ടെന്ന് നടക്കും. എന്നാൽ ആയിരക്കണക്കിന് മോഡ്യൂളുകളുള്ള ഒരു വലിയ monorepo-യിൽ ഇത് ഒരു വലിയ തലവേദനയാണ്. ഒരു കോർ പാക്കേജിലെ (core package) ഒരു utility type മാറ്റിയാൽ, ഇൻഫേർഡ് ടൈപ്പുകൾ ഇപ്പോഴും ശരിയാണോ എന്ന് പരിശോധിക്കാൻ കംപൈലർ ഓരോ കൺസ്യൂമറെയും (consumer) വീണ്ടും പരിശോധിക്കുന്നു. ബിൽഡ് സമയം ഫയലുകളുടെ എണ്ണത്തിനനുസരിച്ചല്ല, മറിച്ച് dependency depth-ന് അനുസരിച്ചാണ് കൂടുന്നത്. ഒരു ചെറിയ റീഫാക്ടർ (refactor) പോലും മുഴുവൻ ഗ്രാഫിന്റെയും പുനർകണക്കുകൂട്ടലിന് (recomputation) കാരണമായേക്കാം. ടീമുകൾ പലപ്പോഴും ഇത് ഒഴിവാക്കാനാവാത്ത ഒന്നായി കണക്കാക്കുന്നു. എന്നാൽ അത് അങ്ങനെയല്ല.

isolatedDeclarations എങ്ങനെ പ്രവർത്തിക്കുന്നു

ഈ പുതിയ ഫ്ലാഗ് നിങ്ങളും കംപൈലറും തമ്മിലുള്ള കരാർ മാറ്റുന്നു. നിങ്ങളുടെ എക്സ്‌പോർട്ടുകളുടെ (exports) ടൈപ്പുകൾ ഇൻഫർ (infer) ചെയ്യാൻ TypeScript-നോട് ആവശ്യപ്പെടുന്നതിന് പകരം, നിങ്ങൾ അവ സ്വയം അനോട്ടേറ്റ് (annotate) ചെയ്യുന്നു. ഈ ഒരു മാറ്റം ഗ്ലോബൽ നോളജിന്റെ (global knowledge) ആവശ്യകത ഇല്ലാതാക്കുന്നു. നിങ്ങളുടെ മോഡ്യൂളിന് ഡെക്ലറേഷൻസ് പുറത്തിറക്കാൻ കംപൈലറിന് ഇനി നിങ്ങളുടെ ഡെപെൻഡൻസികൾ വിശകലനം ചെയ്യേണ്ടതില്ല. അത് അതിന്റെ മുന്നിലുള്ള സിന്റാക്സ് (syntax) മാത്രം നോക്കുന്നു.

ഇതിനർത്ഥം ഓരോ ഫയലിനും അതിന്റെ .d.ts ഔട്ട്പുട്ട് സ്വതന്ത്രമായും സമാന്തരമായും (parallel) പുറത്തിറക്കാൻ കഴിയും എന്നാണ്. ഡെക്ലറേഷൻ ജനറേഷൻ തുടങ്ങുന്നതിന് മുമ്പ് ബിൽഡ് ടൂളിന് ഒരു പൂർണ്ണമായ type graph നിർമ്മിക്കേണ്ടതില്ല. മുമ്പ് type checker ഇല്ലാത്തതിനാൽ .d.ts എമിറ്റ് (emit) ചെയ്യാതിരുന്ന esbuild, swc പോലുള്ള ടൂളുകൾക്ക് ഇപ്പോൾ ട്രാൻസ്പൈലേഷൻ (transpilation) വേഗതയിൽ തന്നെ ഡെക്ലറേഷൻസ് നിർമ്മിക്കാൻ കഴിയും. അവ സോഴ്സിൽ നിന്നുള്ള എക്സ്പ്ലിസിറ്റ് അനോട്ടേഷനുകൾ നേരിട്ട് വായിക്കുകയും ടൈപ്പ് ഇക്വേഷനുകൾ (type equations) പരിഹരിക്കാതെ തന്നെ അനുയോജ്യമായ ടൈപ്പ് ഡെഫനിഷനുകൾ എഴുതുകയും ചെയ്യുന്നു.

മുമ്പ്, .d.ts ഫയലുകൾ നിർമ്മിക്കാൻ ആവശ്യമായ ടൈപ്പ് ഇൻഫർമേഷൻ ഔദ്യോഗിക കംപൈലറിന് മാത്രമേ ഉണ്ടായിരുന്നതുകൊണ്ട് ഡെക്ലറേഷൻ എമിറ്റ് എന്നത് tsc-യുടെ കുത്തകയായിരുന്നു. വേഗതയേറിയ ട്രാൻസ്പൈലറുകൾക്ക് ടൈപ്പുകൾ നീക്കം ചെയ്യാനോ സിന്റാക്സ് മാറ്റാനോ കഴിയുമായിരുന്നു, എന്നാൽ അവയ്ക്ക് ടൈപ്പ് ഡെഫനിഷനുകൾ നിർമ്മിക്കാൻ കഴിയില്ലായിരുന്നു. isolatedDeclarations-ലൂടെ, ഡെക്ലറേഷൻ വർക്ക്ഫ്ലോകൾ കൈകാര്യം ചെയ്യാൻ മുഴുവൻ ഇക്കോസിസ്റ്റത്തിനും (ecosystem) അവസരം ലഭിക്കുന്നു. മാറ്റം ലോജിക്കൽ എന്നതിലുപരി മെക്കാനിക്കൽ (mechanical) ആയി മാറുന്നു. ആ വ്യത്യാസമാണ് പത്ത് മിനിറ്റ് കാത്തിരിപ്പിനെ സെക്കൻഡുകളാക്കി മാറ്റുന്നത്.

വിട്ടുവീഴ്ചകൾ: Explicit ആണ് പുതിയ ഡിഫോൾട്ട്

വേഗതയ്ക്ക് ഒരു വില നൽകേണ്ടതുണ്ട്. ഓരോ എക്സ്‌പോർട്ട് ചെയ്ത ഫങ്ക്ഷനും ക്ലാസ്സും വേരിയബിളും ഒരു എക്സ്പ്ലിസിറ്റ് ടൈപ്പ് അനോട്ടേഷൻ (explicit type annotation) ഉണ്ടായിരിക്കണം. നിങ്ങളുടെ പബ്ലിക് API (public API) നിങ്ങൾക്കായി ഇൻഫർ ചെയ്യാൻ TypeScript വിസമ്മതിക്കും.

ഒരു ലളിതമായ യൂട്ടിലിറ്റി പരിഗണിക്കുക:

export function getUser(id: number) {
  return fetchUser(id);
}

isolatedDeclarations എനേബിൾ ചെയ്താൽ, ഇതിൽ എറർ (error) കാണിക്കും. പരിശോധിക്കാതെ തന്നെ fetchUser-ന്റെ റിട്ടേൺ ടൈപ്പ് അറിയാൻ കംപൈലറിന് കഴിയില്ല, കൂടാതെ ഈ ഫ്ലാഗിന് കീഴിൽ