ನೀವು ಎಂದಾದರೂ TypeScript monorepo ಗೆ ಎರಡು ಸಾಲುಗಳ ಬಗ್ಫಿಕ್ಸ್ (bugfix) ಅನ್ನು ಪುಶ್ ಮಾಡಿ, ನಿಮ್ಮ ಬಿಲ್ಡ್ ಪೈಪ್ಲೈನ್ ಹತ್ತು ನಿಮಿಷಗಳ ಕಾಲ type checking ಮಾಡುವ ಪ್ರಕ್ರಿಯೆಯನ್ನು ನೋಡಿದ್ದರೆ, ನಿಮಗೆ ಈಗಾಗಲೇ ಸಮಸ್ಯೆಯ ಅರಿವಿದೆ. ಈ ವಿಳಂಬವು bundling ನಿಂದಲ್ಲ. ಇದು minification ನಿಂದಲ್ಲ. ಇದು TypeScript ನಿಮ್ಮ declaration files ಬರೆಯಲು ಪ್ರಯತ್ನಿಸುವ ಕ್ಷಣದಲ್ಲಿ ಸಂಭವಿಸುತ್ತದೆ. ಒಂದು .d.ts ಫೈಲ್ ಅನ್ನು ಹೊರಸೂಸುವ (emit) ಮೊದಲು, compiler ಸಂಪೂರ್ಣ type graph ಅನ್ನು ಪರಿಹರಿಸಬೇಕಾಗುತ್ತದೆ (resolve ಮಾಡಬೇಕಾಗುತ್ತದೆ). ಇದು imports ಗಳನ್ನು ಹುಡುಕುತ್ತದೆ, generics ಗಳನ್ನು ಮೌಲ್ಯಮಾಪನ ಮಾಡುತ್ತದೆ ಮತ್ತು ಮೂರು dependency layers ಆಳದಲ್ಲಿರುವ return types ಗಳನ್ನು ಅಂದಾಜಿಸುತ್ತದೆ (infers). ನೀವು ಬದಲಾಯಿಸಿದ ಆ ಒಂದು ಫೈಲ್ ಮತ್ತೊಂದು ಫೈಲ್ ಅನ್ನು ಪ್ರಭಾವಿಸುತ್ತದೆ, ಅದು ಮೂರನೇ ಫೈಲ್ ಅನ್ನು ಪ್ರಭಾವಿಸುತ್ತದೆ, ಮತ್ತು ಇದ್ದಕ್ಕಿದ್ದಂತೆ ನಿಮ್ಮ function ಏನು return ಮಾಡುತ್ತದೆ ಎಂದು ವಿವರಿಸಲು compiler ಇಡೀ repository ಉದ್ದಕ್ಕೂ ತನಿಖೆ ನಡೆಸಬೇಕಾಗುತ್ತದೆ.
ಈ ಅಭ್ಯಾಸವನ್ನು ಮುರಿಯಲು TypeScript 6.0 isolatedDeclarations ಅನ್ನು ಪರಿಚಯಿಸುತ್ತದೆ.
ನಿಜವಾದ ಅಡಚಣೆ (The Real Bottleneck)
Declaration files ಎಂಬವು ನಿಮ್ಮ ಕೋಡ್ನ ಸಾರ್ವಜನಿಕ ಒಪ್ಪಂದದಂತಿವೆ (public contract). ಇನ್ನೊಬ್ಬ ડેವಲಪರ್ ನಿಮ್ಮ package ಅನ್ನು import ಮಾಡಿದಾಗ, TypeScript ಮೂಲ ಕೋಡ್ ಅನ್ನು (source) ಓದುವ ಬದಲು .d.ts ಫೈಲ್ಗಳನ್ನು ಓದುತ್ತದೆ. ಆ ಫೈಲ್ಗಳನ್ನು ಸರಿಯಾಗಿ ತಯಾರಿಸಲು compiler type checker ಅನ್ನು ಬಿಟ್ಟುಬಿಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಒಂದು ಸಾಲಿನ ಔಟ್ಪುಟ್ ಬರೆಯುವ ಮೊದಲು, ಅದು ಪ್ರತಿಯೊಂದು shape, ಪ್ರತಿಯೊಂದು union ಮತ್ತು ಪ್ರತಿಯೊಂದು inferred return type ಅನ್ನು ತಿಳಿದಿರಬೇಕು.
ಐವತ್ತು ಫೈಲ್ಗಳಿರುವ ಸಣ್ಣ ಪ್ರಾಜೆಕ್ಟ್ನಲ್ಲಿ ಇದು ತಕ್ಷಣವೇ ಆಗುತ್ತದೆ. ಆದರೆ ಸಾವಿರಾರು modules ಇರುವ ದೊಡ್ಡ monorepo ನಲ್ಲಿ, ಇದು ಒಂದು ಸರಣಿ ದುಸ್ವಪ್ನದಂತಿದೆ (serialized nightmare). ಒಂದು core package ನಲ್ಲಿ utility type ಅನ್ನು ಬದಲಾಯಿಸಿದರೆ, compiler ಪ್ರತಿಯೊಂದು consumer ಅನ್ನು ಮರುಪರಿಶೀಲಿಸುತ್ತದೆ ಮತ್ತು inferred types ಇನ್ನೂ ಸರಿಯಾಗಿವೆಯೇ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳುತ್ತದೆ. ಬಿಲ್ಡ್ ಸಮಯವು ಕೇವಲ ಫೈಲ್ ಸಂಖ್ಯೆಯ ಮೇಲೆ ಮಾತ್ರವಲ್ಲದೆ, dependency ಆಳದ ಮೇಲೆ ಅವಲಂಬಿತವಾಗಿರುತ್ತದೆ. ಒಂದು ಸಣ್ಣ refactor ಕೂಡ ಇಡೀ graph ಅನ್ನು ಮರು-ಲೆಕ್ಕಾಚಾರ ಮಾಡುವಂತೆ ಮಾಡಬಹುದು. ತಂಡಗಳು ಇದನ್ನು ಅನಿವಾರ್ಯ ಎಂದು ಒಪ್ಪಿಕೊಳ್ಳುತ್ತವೆ. ಆದರೆ ಅದು ಅನಿವಾರ್ಯವಲ್ಲ.
isolatedDeclarations ಹೇಗೆ ಕೆಲಸ ಮಾಡುತ್ತದೆ
ಈ ಹೊಸ flag ನೀವು ಮತ್ತು compiler ನಡುವಿನ ಒಪ್ಪಂದವನ್ನು ಬದಲಾಯಿಸುತ್ತದೆ. ನಿಮ್ಮ exports ಗಳ types ಅನ್ನು ಅಂದಾಜಿಸಲು (infer ಮಾಡಲು) TypeScript ಗೆ ಕೇಳುವ ಬದಲು, ನೀವೇ ಅವುಗಳಿಗೆ annotations ನೀಡಬೇಕು. ಈ ಒಂದು ಬದಲಾವಣೆಯು global knowledge ನ ಅಗತ್ಯವನ್ನು ಇಲ್ಲದಂತೆ ಮಾಡುತ್ತದೆ. ನಿಮ್ಮ module ಗಾಗಿ declarations ಅನ್ನು ಹೊರಸೂಸಲು compiler ಇನ್ನು ಮುಂದೆ ನಿಮ್ಮ dependencies ಅನ್ನು ವಿಶ್ಲೇಷಿಸುವ ಅಗತ್ಯವಿಲ್ಲ. ಅದು ತನ್ನ ಮುಂದೆ ಇರುವ syntax ಅನ್ನು ಮಾತ್ರ ನೋಡುತ್ತದೆ.
ಇದರರ್ಥ ಪ್ರತಿಯೊಂದು ಫೈಲ್ ತನ್ನ .d.ts ಔಟ್ಪುಟ್ ಅನ್ನು ಸ್ವತಂತ್ರವಾಗಿ ಮತ್ತು ಸಮಾಂತರವಾಗಿ (in parallel) ಹೊರಸೂಸಬಹುದು. Declaration generation ಪ್ರಾರಂಭಿಸುವ ಮೊದಲು build tool ಸಂಪೂರ್ಣ type graph ಅನ್ನು ನಿರ್ಮಿಸುವ ಅಗತ್ಯವಿಲ್ಲ. ಈ ಹಿಂದೆ type checker ಇಲ್ಲದ ಕಾರಣ .d.ts emit ಮಾಡುವುದನ್ನು ತಪ್ಪಿಸುತ್ತಿದ್ದ esbuild ಮತ್ತು swc ನಂತಹ tools ಈಗ near-transpilation ವೇಗದಲ್ಲಿ declarations ಅನ್ನು ತಯಾರಿಸಬಹುದು. ಅವು ನೇರವಾಗಿ source ನಿಂದ explicit annotations ಗಳನ್ನು ಓದುತ್ತವೆ ಮತ್ತು ಯಾವುದೇ type equations ಗಳನ್ನು ಬಿಡಿಸದೆ ಸಂಬಂಧಿತ type definitions ಗಳನ್ನು ಬರೆಯುತ್ತವೆ.
ಈ ಹಿಂದೆ, .d.ts ಫೈಲ್ಗಳನ್ನು ತಯಾರಿಸಲು ಅಗತ್ಯವಿರುವ type information ಕೇವಲ ಅಧಿಕೃತ compiler ವೊಂದರ ಬಳಿ ಮಾತ್ರ ಇರುವುದರಿಂದ, declaration emit ಎಂಬುದು tsc ನ ಏಕಸ್ವಾಮ್ಯವಾಗಿತ್ತು. ವೇಗದ transpilers ಗಳು types ಗಳನ್ನು ತೆಗೆದುಹಾಕಬಹುದು ಅಥವಾ syntax ಅನ್ನು ಬದಲಾಯಿಸಬಹುದು, ಆದರೆ ಅವು type definitions ಗಳನ್ನು ತಯಾರಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿರಲಿಲ್ಲ. isolatedDeclarations ಮೂಲಕ, ಇಡೀ ecosystem declaration workflows ಅನ್ನು ನಿರ್ವಹಿಸಲು ಅವಕಾಶ ಸಿಗುತ್ತದೆ. ಈ ಪರಿವರ್ತನೆಯು logical ಆಗಿರುವುದಕ್ಕಿಂತ ಹೆಚ್ಚಾಗಿ mechanical ಆಗಿರುತ್ತದೆ. ಈ ವ್ಯತ್ಯಾಸವೇ ಹತ್ತು ನಿಮಿಷಗಳ ಕಾಯುವಿಕೆಯನ್ನು ಸೆಕೆಂಡುಗಳಿಗೆ ಬದಲಾಯಿಸುತ್ತದೆ.
The Tradeoff: Explicit ಎಂಬುದು ಹೊಸ ಡಿಫಾಲ್ಟ್
ವೇಗವು ಒಂದು ನೇರವಾದ ಬೆಲೆಯನ್ನು ತರುತ್ತದೆ. ಪ್ರತಿಯೊಂದು exported function, class ಮತ್ತು variable ಕಡ್ಡಾಯವಾಗಿ explicit type annotation ಅನ್ನು ಹೊಂದಿರಬೇಕು. TypeScript ನಿಮಗಾಗಿ public API ಅನ್ನು ಅಂದಾಜಿಸಲು (infer ಮಾಡಲು) ನಿರಾಕರಿಸುತ್ತದೆ.
ಒಂದು ಸರಳ utility ಅನ್ನು ಗಮನಿಸಿ:
export function getUser(id: number) {
return fetchUser(id);
}
isolatedDeclarations ಅನ್ನು ಎನೇಬಲ್ ಮಾಡಿದಾಗ, ಇದು error ತೋರಿಸುತ್ತದೆ. compiler ಅದನ್ನು ಪರಿಶೀಲಿಸದೆ fetchUser ನ return type ಅನ್ನು ತಿಳಿಯಲು ಸಾಧ್ಯವಿಲ್ಲ, ಮತ್ತು ಈ flag ಅಡಿಯಲ್ಲಿ
