- Node.js PR #53725 merge होने के बाद
--experimental-strip-types flag के जरिए TypeScript files चलाने के लिए experimental support मिला
- यह feature TypeScript source से type syntax हटाकर उसे JavaScript source में बदलता है, और conversion के दौरान type checking नहीं करता
- शुरुआती implementation
Enum, namespaces जैसी TypeScript-only features को transform नहीं करती, इसलिए यह सिर्फ ऐसे code तक सीमित है जो type हटाने भर से JavaScript बन जाता है
- implementation के लिए
@swc/wasm-typescript चुना गया, वजह यह simplicity है कि Node.js toolchain में Rust या Go जोड़ने की जरूरत नहीं पड़ती
- चर्चा में ESM के mandatory file extension rules, TypeScript की यह practice कि
.js import असल में .ts file की ओर point करता है, और sourcemap व error stack location की लागत प्रमुख constraints के रूप में सामने आए
--experimental-strip-types कैसे काम करता है
--experimental-strip-types set करने पर Node.js TypeScript files चला सकता है
- Node.js TypeScript source code को JavaScript source code में transpile करता है
- Transpile process में type checking नहीं की जाती, और type information छोड़ दी जाती है
- उदाहरण इस तरह है
const foo: string = "foo";
const foo = "foo";
सिर्फ type removal चुनने की वजह और शुरुआती सीमाएं
- इस PR का core TypeScript syntax में से type syntax removal है
- दूसरे runtimes
enum जैसी JavaScript में न मौजूद TypeScript-only features को JavaScript में transform भी करते हैं
- इस PR की शुरुआती implementation ऐसे transformations नहीं करती
Enum इस्तेमाल नहीं किया जा सकता
namespaces इस्तेमाल नहीं किए जा सकते
- अन्य TypeScript-only features भी transform target नहीं हैं
- implementation details और limitations के लिए PR changes में
typescript.md देखने की सलाह शामिल है
Implementation tool के रूप में @swc/wasm-typescript का चयन
@swc/wasm-typescript एक छोटा package है, और यह wasm file व उसे bind करने वाली JavaScript file से बना है
- दूसरे tools में Node.js toolchain में Rust या Go जोड़ने की requirement थी
- SWC इसी उद्देश्य के लिए Deno में भी इस्तेमाल हो रहा है, और PR author ने इसे validated option माना
- आगे चलकर यह feature native layer में implement हो सकता है, ऐसा माना गया
- यह PR nodejs/loaders#217 को reference करता है
import resolution और extension पर चर्चा
import foo from "./foo" जैसे extension-less imports support नहीं किए जाते
- Node.js ESM में mandatory file extensions rule है, इसलिए extension-less import का support न होना intended behavior माना गया
- यह राय आई कि TypeScript module codebases में actual file
.ts होने के बावजूद import statement में .js extension लिखना आम है
- उदाहरण:
import foo from './foo.js'
- जब actual file system में
./foo.js नहीं होता और सिर्फ ./foo.ts होता है
- PR author के अनुसार इस समस्या को future iterations में address किया जा सकता है, और extension guessing के लिए additional file system checks व heuristics की जरूरत होगी
- अगर
./foo.js नहीं है तो ./foo.ts check करें
- अगर
./foo.ts नहीं है तो ./foo.js check करें
- यह चर्चा nodejs/loaders#208 में track की जा रही है
Source location, sourcemap, error stack
- Review में यह राय आई कि error stack की accurate source location short term में जरूरी है
- एक संभव तरीका यह है कि type removal process में source location न बदले, ताकि sourcemap generation और mapping से बचा जा सके
- Sourcemap में memory usage और performance के लिहाज से लागत है, और इसके सरल न होने की constraint बताई गई
- PR author के मुताबिक SWC पहले से sourcemap support करता है, इसलिए इसे enable करने वाला flag जोड़ा जा सकता है
- हटाए गए syntax को whitespace से replace करके original error stack को न बदलने वाला option भी SWC से request किया जा सकता है
Stabilization से पहले बाकी design issues
- TypeScript support दो हिस्सों में बंटा है
- type syntax removal
.ts files accept करने के लिए resolution rules adjust करना
- Resolution rules में बदलाव से existing TypeScript loaders के साथ conflict हो सकता है, ऐसी चिंता सामने आई
- PR author ने जवाब दिया कि इस PR में resolution rule override नहीं है, और file extension जरूरी है
allowImportingTsExtensions के जरिए import './file.ts' form support किया जा सकता है, और यह तरीका Deno से भी match करता है, ऐसी राय दी गई
- अगर वही source file सीधे run करनी हो और build tool से JavaScript output भी बनाना हो, तो
file.ts को file.js में बदलने की जिम्मेदारी build tool ले सकता है, ऐसा माना गया
Merge और follow-up work
- PR 24 जुलाई 2024 को
nodejs:main में merge हुआ
- Change size 8 commits, 89 files, 2,190 lines added और 25 lines deleted का है
semver-minor, experimental, module, esm, notable-change जैसे labels लगे
- Website के TypeScript guide page में इस feature का उल्लेख किया जाए या नहीं, इस पर चर्चा हुई, और related update PR भी link हुआ
- Distribution metadata में Node binary द्वारा type removal के लिए इस्तेमाल की जाने वाली TypeScript version शामिल करने का तरीका भी follow-up issue के रूप में discuss हुआ
1 टिप्पणियां
Hacker News की राय
TypeScript type stripping TypeScript syntax के बिना संभव नहीं है। Type stripping token-level काम नहीं है, और TypeScript syntax लगातार बदलता रहता है
उदाहरण के लिए
foo < bar & baz > ( x )TypeScript 1.5 में(foo (x))की तरह parse होता था, क्योंकिbar&bazvalid type expression नहीं था; लेकिन intersection type operator जुड़ने के बाद यहfoo<(bar & baz)>(x)के रूप में parse होकरfoo(x)में disambiguate हुआअगर नवीनतम TypeScript features लगातार इस्तेमाल करने हैं, तो JS में compile करना होगा या Node version हमेशा latest रखना होगा; और जो teams Node LTS पर रहना पसंद करती हैं, उनके लिए यह स्वीकार करना मुश्किल compromise हो सकता है
Core में stable version रखा जाए, लेकिन जब TypeScript नई features या breaking changes लाए, या user नए experimental features इस्तेमाल करना चाहे, तो NPM से अलग upgrade कराया जाए
इससे users lock-in नहीं होंगे, और फिर भी Node.js release के 3 साल के lifecycle के दौरान किसी खास TypeScript version को support किया जा सकेगा: https://github.com/nodejs/loaders/issues/217
आखिरी बड़ा syntax change शायद 2.8 का conditional types था, जब type position में ternary
ifoperator जैसी syntax आई थी। Type checking तक करनी हो तो type model 2.x के बाद काफी बदला है, लेकिन syntax कुल मिलाकर stable रहा है और TypeScript में innovation भी ज्यादातर type model और type inference की तरफ रही हैअभी यह शुरुआती Stage 1 में है, लेकिन type checking नहीं, बल्कि type stripping के उद्देश्य से TypeScript type syntax के बड़े हिस्से को standardize करने की कोशिश भी है: https://github.com/tc39/proposal-type-annotations
जिन teams को latest V8 या Node features में खास रुचि नहीं है और वे LTS पर रहती हैं, उनकी latest TypeScript features में भी कम रुचि होने की संभावना है
अगर Node.js TypeScript files को सीधे चला सके, तो TypeScript compiler को type stripping और JavaScript transformation के बजाय केवल type checker के रूप में इस्तेमाल किया जा सकता है। यह Python में type checker द्वारा types की जांच कर उन्हें जस का तस छोड़ने और interpreter द्वारा type hints को ignore करने के तरीके जैसा है
दिलचस्प है कि Python में एक ही type hint syntax इस्तेमाल करते हुए भी अलग semantics वाले कई popular type checkers बने। इसके उलट JavaScript में TypeScript ही लगभग अकेला popular type checker बन गया लगता है
Python में मैंने ऐसे cases भी सुने हैं जहाँ लोग type check किए बिना source में सिर्फ types लिखते हैं, जैसे ज्यादा सुविधाजनक comment syntax। अगर Node.js type ignoring support करे, तो JavaScript में भी ऐसा तरीका संभव हो जाएगा
व्यक्तिगत रूप से JSDoc इस्तेमाल करने में मेरी सबसे बड़ी असुविधा import syntax थी, लेकिन TypeScript 5.5 के बाद यह बदल गया और अब समस्या नहीं रही
हालांकि कुछ bundlers पहले से SWC जैसे unofficial compilers का इस्तेमाल करके यह काम कर रहे हैं, और Node भी इस feature में SWC को test कर रहा है
Type hints सिर्फ साधारण comments नहीं, बल्कि नाम की तरह IDE को बेहतर autocomplete दिखाने के लिए hints भी हैं
मुझे लगता है इसे language specification का हिस्सा होना चाहिए
यह जानने की उत्सुकता है कि अगर यह फीचर flag के पीछे रहने के बजाय default बन जाता है, तो NPM ecosystem कैसे प्रतिक्रिया देगा। यह नहीं पता कि contributors NPM modules publish करते समय अब भी CJS और ESM versions build करेंगे, या फिर
package.jsonमें सिर्फengine: nodejs >= 25लगाकर build step छोड़ देंगेनिजी तौर पर, अगर TS source वाले NPM modules
dist/.cjsdistribution बंद कर दें, तो debugger औरconsole.logकहाँ डालना है यह ज्यादा साफ हो जाएगा, इसलिए यह बेहतर लगेगा। NPM contributors के लिए भी build step हटाने का लालच बड़ा होगालेकिन अगर सिर्फ एक dependency भी TS file distribute करती है, तो “सबको TS files मिलती हैं” वाली धारणा तेजी से फैल सकती है। जैसे ही Node.js इसे opt-in experimental flag से बाहर लाएगा, पूरी community consumers से TS files स्वीकार करने की मौन उम्मीद करने लगेगी
ऐसा हुआ तो कुछ महीनों में Firefox और Safari पर भी इसे अपनाने का दबाव पड़ेगा, और सभी JS compilers को TS type annotations हटाने ही पड़ेंगे
निजी तौर पर मुझे यह भी ठीक लगता है। TS इस्तेमाल करने वाले भी किसी काल्पनिक JS user support के लिए TS code को JS और
.d.tsमें बदलने वाला transformation step NPM modules में डाल रहे हैं। लेकिन अगर Node.tsfiles स्वीकार कर लेता है, तो ऐसे transformation step को अनजाने में हटाया जा सकता है; इसलिए यह जानने की उत्सुकता है कि NPM publishers कोjs/d.tsfiles distribute करना बंद करके भी टूट-फूट का पता न चलने से रोकने के लिए क्या सुरक्षा होगीइसमें बिना build step के TypeScript code upload किया जा सकता है, और जब कोई दूसरा developer install करता है, तो वह transformed JavaScript के बजाय original TypeScript source देख सकता है
.tsfiles चलाना supported नहीं है। ecosystem को न तोड़ने के लिए यह मुख्य constraints में से एक है.cjsऔर.mjsमें transform किया जा रहा है, और शायद वे तीनों versions ही distribute करेंगेअगर कोई नया project शुरू से लिखा जा रहा है, तो हो सकता है वह सिर्फ TypeScript distribute करे और transform न करे
संपादन: PR author और Node.js Technical Steering Committee member लगने वाले satanacchio के sibling comment के अनुसार, TS support top-level items के लिए है और
node_modulesके अंदर libraries पर लागू नहीं होता.tsको npm पर publish करना चाहता हूँ, लेकिन TypeScript teamtsconfigissues और performance issues की वजह से इसके बहुत खिलाफ थी। फिर भी उम्मीद हैशायद कभी Node JS में इन types पर runtime reflection कर सके
तब यह बहुत बड़ा फायदा होगा। Python में types पर reflection संभव है, इसलिए pydantic जैसे शानदार tools types से validations generate कर सकते हैं
एक ही standard notation से type checking, runtime data validation, API generation, और API documentation generation मिल सकते हैं
आज JS में Zod जैसे tools को
const mySchema = z.string();की तरह वही चीज लगभग फिर से invent करनी पड़ती है जो TypeScript पहले से करता हैz.string()सिर्फ TypeScript जैसी type safety नहीं देता। TypeScript compile-time type checking देता है, और Zod runtime validation और parsing जोड़ता हैz.string()mySchemaको parsing और validation करने योग्य functional schema बनाता है।mySchema.parse("some data")सफल होता है, औरmySchema.parse(321)exception फेंकता हैजहाँ runtime validation और in-process checks की जरूरत थी, वहाँ इसे इस्तेमाल किया है और यह काफी अच्छे से काम करता है;
const A = z.string(); type A = z.infer; // stringकी तरह type भी निकाल सकते हैंयानी Zod में पहले type define करके वहाँ से type infer करें, तो compile-time और runtime type checking दोनों मिलते हैं। हालांकि तेजी से बदलते छोटे codebase के लिए यह overkill हो सकता है, लेकिन in-process validation की जरूरत वाली situations में यह काफी उपयोगी है और काम भी ज्यादा नहीं है
हालांकि TypeScript plugins allow करता है। वे ज्यादा इस्तेमाल नहीं होते, लेकिन language में ऐसे दूसरे features जोड़ सकते हैं जो resulting JavaScript में transform होते हैं
runtime types से जुड़ा एक plugin Typia है, जो
assert(myValue)जैसे guards में TypeScript type signatures को runtime पर इस्तेमाल करने देता है। यह function call को intercept करके transformed JavaScript में passed variable की प्रकृति जांचने वाले exhaustiveifstatements generate करता हैअगले 4–6 साल में यह language का हिस्सा बनेगा ऐसा नहीं लगता, लेकिन ऐसी चीजें आज भी करने देने वाली libraries पहले से मौजूद हैं
असल में sound type system की जरूरत है, लेकिन TS जानबूझकर sound नहीं है। TS जैसी खराब coding practices allow न करने वाला, और programs को तेज बनाने वाली design enforce करने वाला type system चाहिए। Hindley-Milner type system चाहिए
अगर किसी module को typed code बनाना हो, तो
"use type"जोड़ने जैसा तरीका हो सकता है। इस mode में type coercion जैसी खराब चीजों पर रोक लगनी चाहिए, और object shapes या value types बदलने, या किसी भी values को मिलाकर array बनाने जैसी performance को नुकसान पहुंचाने वाली चीजों को रोकना चाहिएuntyped modules से आने वाला data transform किया जाए या transform न हो सके तो error फेंके; तब compiler ज्यादा मजबूत type guarantees और deoptimization के जोखिम के बिना typed code को गहराई से optimize कर सकेगा
ValueErrorकी subclass है या objectSomeClassका instance है। मैं TS में नया हूँ, इसलिए सोचता था कि array, object, number, string के अलावा JS में types नहीं होते, और Zod या type guard functions “भरोसा करो” स्तर के सामान्य objects return करते हैंBun का developer experience इस क्षेत्र में काफी अभूतपूर्व स्तर का है, और अब ज़्यादातर use cases कवर हो चुके हैं या
bun runसे execution scripts लिखते समय Bun क्रैश नहीं होतावहीं Node को ऐसा सेट भी नहीं किया जा सकता कि import में extension की ज़रूरत न पड़े, और
tscसे compile output में.jsextension अपने-आप जुड़वाया भी नहीं जा सकता, इसलिए bundler जोड़ना पड़ता हैnative TypeScript support इस छोटी-सी असुविधा को काफी हद तक ठीक कर देगा, लेकिन stable हो जाने पर भी user experience या performance Bun के बराबर होगी, इसकी कल्पना करना मुश्किल है
developer experience और tools भी top-tier हैं। Deno type checking भी कर सकता है, और जहां तक याद है, TSC को bundle करता है
Bun की hype ज़्यादा है, लेकिन serious काम के लिए फिलहाल Deno साफ़ तौर पर बेहतर विकल्प है। फिर भी Bun का vision और execution प्रभावशाली है और developers के लिए अच्छी बात है
bun installचलाना fail हुआ, इसलिए एक बार भी ठीक से काम नहीं कर पाया: https://github.com/search?q=repo%3Aoven-sh%2Fbun+bun+install...मैं लंबे समय से TypeScript runtime चाहता था और TypeScript भी सचमुच पसंद है, लेकिन मज़ेदार है कि बहुत पहले Java छोड़ने के बाद आखिरकार मैं ऐसी चीज़ खोजने लगा जो Java के कहीं ज़्यादा करीब है
आखिरकार शायद हम जो चाहते थे वह JIT, ज़्यादा समृद्ध type system और gradual types वाला Java ही था। npm ecosystem में भी कई कमियां हैं, लेकिन इस ecosystem में libraries इस्तेमाल करना कहीं कम बोझिल और ज़्यादा मज़ेदार है
हैरानी की बात है कि Rust भाषा-spectrum के दूसरे छोर पर है, फिर भी कभी-कभी वैसा ही एहसास देता है
सुधार: JIT कहना ठीक नहीं था। मैंने आलस में JIT लिख दिया, लेकिन मेरा मतलब JVM और V8 में कुछ चलाते समय startup time और runtime के फर्क से था। Java भारी लगता है, जबकि JavaScript ecosystem कहीं ज़्यादा agile लगता है
TypeScript Java के ज़्यादा करीब है, यह भी मुझे बिल्कुल नहीं लगता। दोनों में साझा बस “Javascript” नाम की गलतबयानी और imperative programming support जैसी चीज़ें हैं, बाकी वे बहुत अलग हैं
हालांकि Java में एक चीज़ है जिसकी TypeScript में कमी खलती है: runtime type reflection। TypeScript ecosystem में इसे bypass करने के अनगिनत तरीके हैं, लेकिन मुझे वे सभी थोड़े बदसूरत लगते हैं
AoT भी ठीक है और single binary option हो तो अच्छा होगा। आदर्श रूप से runtime न हो और smart elimination संभव हो। browser में JIT से भी चले तो और बेहतर
exhaustive pattern matching जैसे compiler और type checker convenience features भी चाहिए
Deno का मेरा पसंदीदा feature सीधे Node में आ रहा है। बहुत बढ़िया
अब शायद type stripping के लिए हमेशा esbuild install नहीं करना पड़ेगा। TypeScript में scripts लिखकर इस्तेमाल करना बहुत आसान हो जाएगा, इसकी उम्मीद है
हाल में मैं one-off scripts के लिए Python पसंद करता था, लेकिन types के लिहाज़ से व्यक्तिगत रूप से TypeScript को Python से बेहतर मानता हूं। खासकर वे बड़े scripts जिन्हें कुछ महीनों बाद फिर देखना हो, types से काफी फायदा मिलता है
ts-nodeभी है, लेकिन निजी तौर पर मैंtsxपसंद करता हूंhttps://github.com/privatenumber/tsx
Node के लिए सचमुच घटनाओं से भरा महीना रहा। पहले v22.5.0 में node:sqlite जोड़ा गया, और अब TypeScript support भी आ रहा है। Node जिस दिशा में जा रहा है, वह मुझे पसंद है
PR author हूं। कुछ भी पूछ सकते हैं
बहुत पहले मैंने backend काम के लिए Node.js इस्तेमाल करना शुरू किया था, और लगा कि PHP में code लिखने की तुलना में इसके कई फायदे हैं, साथ ही यह Java वाली बहुत-सी समस्याएँ भी साथ नहीं लाता
लेकिन Node थोड़ा रफ-सा था, और ऐसा लगता था जैसे मनचाही language बनाने के लिए इसमें इधर-उधर की चीज़ें जोड़नी पड़ती हों। आखिरकार मैंने Go इस्तेमाल करना शुरू किया, जो कहीं ज़्यादा आसान लगा; कभी-कभी वह काफी ज़्यादा verbose होता है, लेकिन type safety की वजह से coding सरल हो गई
TypeScript एक अच्छा विकल्प लगता था, लेकिन आखिर में वह भी एक और पैबंद ही था। Go की जगह TypeScript इस्तेमाल करने से क्या value मिलती है, यह मुझे साफ नहीं दिखता। स्पष्ट types होना अच्छा है, लेकिन यह language की उन दूसरी समस्याओं को हल नहीं करता जो Go में हल हो चुकी हैं। Deno भी कुछ हद तक इन्हें हल करता है
Go की तुलना में Node का बड़ा फायदा यह है कि इससे जल्दी prototype बनाया जा सकता है, लेकिन TypeScript इस्तेमाल करने पर लगता है कि वह फायदा काफी कम हो जाता है। इसलिए यह तय करना मुश्किल है कि यह अच्छी प्रगति है या Node को अच्छा विकल्प बनाने वाली खासियतों को खो देने जैसा है
“पैबंद” वाली अभिव्यक्ति देखकर लगता है कि समस्या शायद language खुद से ज़्यादा Django जैसे opinionated framework की कमी हो सकती है, जो सब कुछ default रूप से manage करता हो। Django इस्तेमाल करना मुझे पसंद है, लेकिन तय रास्ते से हटना थोड़ा मुश्किल होता है
cdktfके साथ इस्तेमाल कर रहे हैं, और यह Go से ज़्यादा logical choice लगा