ਤੁਸੀਂ ਇੱਕ ਅਜਿਹਾ type ਲਿਖਦੇ ਹੋ ਜੋ nested objects ਵਿੱਚੋਂ ਲੰਘਦਾ ਹੈ, ਅਤੇ autocomplete ਲਈ dot-separated paths ਬਣਾਉਂਦਾ ਹੈ। ਇਹ ਇੱਕ ਛੋਟੇ test object 'ਤੇ ਬਹੁਤ ਵਧੀਆ ਕੰਮ ਕਰਦਾ ਹੈ। ਫਿਰ ਤੁਸੀਂ ਇਸਨੂੰ ਇੱਕ ਅਸਲੀ API payload 'ਤੇ ਲਗਾਉਂਦੇ ਹੋ, ਅਤੇ editor ਫ੍ਰੀਜ਼ ਹੋ ਜਾਂਦਾ ਹੈ। ਅੰਤ ਵਿੱਚ, TypeScript error TS2589 ਦਿੰਦਾ ਹੈ: Type instantiation is excessively deep and possibly infinite.

ਇਸ ਸੁਨੇਹੇ ਦਾ ਮਤਲਬ ਇਹ ਨਹੀਂ ਹੈ ਕਿ ਤੁਹਾਡੇ ਕੋਡ ਵਿੱਚ ਰਵਾਇਤੀ ਅਰਥਾਂ ਵਿੱਚ ਕੋਈ infinite loop ਹੈ। ਇਸਦਾ ਮਤਲਬ ਇਹ ਹੈ ਕਿ compiler ਨੇ ਹਾਰ ਮੰਨ ਲਈ ਹੈ। ਜਿਸ type ਦੀ ਤੁਸੀਂ ਗਣਨਾ ਕਰਨ ਲਈ ਕਿਹਾ ਸੀ, ਉਹ ਜਾਂ ਤਾਂ ਸੱਚਮੁੱਚ ਅਸੀਮਤ (unbounded) ਸੀ, ਜਾਂ ਫਿਰ ਸੀਮਤ ਸੀ ਪਰ ਇੰਨੀ ਵੱਡੀ ਸੀ ਕਿ ਉਸਦੀ ਗਣਨਾ ਕਰਨ ਨਾਲ TypeScript ਦੀਆਂ ਅੰਦਰੂਨੀ ਸੀਮਾਵਾਂ ਖਤਮ ਹੋ ਜਾਣਗੀਆਂ। ਜਦੋਂ ਅਜਿਹਾ ਹੁੰਦਾ ਹੈ, ਤਾਂ compiler ਤੁਹਾਡੇ IDE ਨੂੰ ਹੈਂਗ ਹੋਣ ਤੋਂ ਬਚਾਉਣ ਲਈ ਰੁਕ ਜਾਂਦਾ ਹੈ।

ਜਦੋਂ TS2589 ਦਿਖਾਈ ਦਿੰਦਾ ਹੈ

Recursive types ਸਭ ਤੋਂ ਆਮ ਕਾਰਨ ਹਨ। TypeScript types ਦੀ ਗਣਨਾ ਬਹੁਤ ਤੇਜ਼ੀ ਨਾਲ ਕਰਦਾ ਹੈ, ਅਤੇ ਜੇਕਰ ਕੋਈ utility type ਵਾਰ-ਵਾਰ ਆਪਣੇ ਆਪ ਨੂੰ ਕਾਲ ਕਰਦਾ ਹੈ—ਖਾਸ ਕਰਕੇ conditional logic ਰਾਹੀਂ—ਤਾਂ computation stack ਤੇਜ਼ੀ ਨਾਲ ਵਧਦਾ ਹੈ। ਤੁਸੀਂ ਆਮ ਤੌਰ 'ਤੇ ਕੁਝ ਖਾਸ ਸਥਿਤੀਆਂ ਵਿੱਚ ਇਸ ਰੁਕਾਵਟ ਦਾ ਸਾਹਮਣਾ ਕਰੋਗੇ:

  • Recursive conditional types ਜੋ ਵਾਰ-ਵਾਰ ਇੱਕ tuple, object, ਜਾਂ string template ਨੂੰ ਉਦੋਂ ਤੱਕ destructure ਕਰਦੇ ਹਨ ਜਦੋਂ ਤੱਕ base case ਨਹੀਂ ਮਿਲ ਜਾਂਦਾ
  • Deeply nested object path generators, ਜੋ { user: { address: { street: string } } } ਵਰਗੀਆਂ structures ਨੂੰ "user" | "user.address" | "user.address.street" ਵਰਗੇ string literals ਦੇ unions ਵਿੱਚ ਬਦਲ ਦਿੰਦੇ ਹਨ
  • Template literal types ਜੋ strings ਨੂੰ character-by-character ਜਾਂ token-by-token parse ਕਰਦੇ ਹਨ
  • Mapped types ਜੋ ਦਰਜਨਾਂ keys ਅਤੇ ਕਈ ਪੱਧਰਾਂ ਵਾਲੇ objects ਉੱਤੇ iterate ਕਰਦੇ ਹਨ
  • Conditional types ਜੋ ਵੱਡੇ unions ਉੱਤੇ distribute ਹੁੰਦੇ ਹਨ, ਜਿਸ ਨਾਲ ਹਰ ਮੈਂਬਰ ਉੱਤੇ ਕੰਮ ਦਾ ਬੋਝ ਚੁੱਪਚਾਪ ਵਧ ਜਾਂਦਾ ਹੈ

Nested path ਵਾਲਾ ਉਦਾਹਰਣ ਖਾਸ ਤੌਰ 'ਤੇ ਆਕਰਸ਼ਕ ਹੁੰਦਾ ਹੈ। Form libraries ਅਤੇ state-management tools field names ਲਈ autocomplete ਪ੍ਰਦਾਨ ਕਰਨਾ ਪਸੰਦ ਕਰਦੇ ਹਨ। ਇੱਕ shallow object 'ਤੇ, ਹਰ ਕਾਨੂੰਨੀ dot-path ਨੂੰ string union ਵਜੋਂ ਬਣਾਉਣਾ ਬਹੁਤ ਸੌਖਾ ਹੈ। ਪਰ ਇੱਕ ਡੂੰਘੇ (deep) ਜਾਂ ਚੌੜੇ (wide) object 'ਤੇ, ਉਹ union ਬਹੁਤ ਵੱਡਾ ਹੋ ਜਾਂਦਾ ਹੈ। TypeScript ਨੂੰ ਇੱਕੋ ਸਮੇਂ ਹਰ permutation ਨੂੰ working memory ਵਿੱਚ ਰੱਖਣਾ ਪੈਂਦਾ ਹੈ। ਇੱਕ ਖਾਸ ਡੂੰਘਾਈ 'ਤੇ, compiler ਨੂੰ ਅਹਿਸਾਸ ਹੁੰਦਾ ਹੈ ਕਿ ਕੰਮ ਉਸਦੇ ਬਜਟ ਤੋਂ ਬਾਹਰ ਜਾ ਰਿਹਾ ਹੈ ਅਤੇ ਉਹ ਐਮਰਜੈਂਸੀ ਬ੍ਰੇਕ ਲਗਾ ਦਿੰਦਾ ਹੈ।

Fix One: ਇੱਕ ਸਖ਼ਤ ਡੂੰਘਾਈ ਸੀਮਾ (Hard Depth Limit) ਜੋੜੋ

TS2589 ਨੂੰ ਹੱਲ ਕਰਨ ਦਾ ਸਭ ਤੋਂ ਸਿੱਧਾ ਤਰੀਕਾ ਇਹ ਹੈ ਕਿ ਇਹ ਮੰਨਣਾ ਛੱਡ ਦਿਓ ਕਿ ਤੁਹਾਡਾ type ਹਮੇਸ਼ਾ ਲਈ recurse ਕਰ ਸਕਦਾ ਹੈ। ਇੱਕ depth counter ਪੇਸ਼ ਕਰੋ ਜੋ circuit breaker ਵਜੋਂ ਕੰਮ ਕਰੇ।

ਵਿਵਹਾਰਕ ਤੌਰ 'ਤੇ, ਇਸਦਾ ਮਤਲਬ ਇੱਕ numeric generic parameter ਜੋੜਨਾ ਹੈ—ਜਿਸ ਨੂੰ ਅਕਸਰ ਇੱਕ tuple ਵਜੋਂ ਦਰਸਾਇਆ ਜਾਂਦਾ ਹੈ ਜਿਸਦੀ ਲੰਬਾਈ ਘਟਦੀ ਜਾਂਦੀ ਹੈ—ਜੋ ਹਰ ਵਾਰ ਜਦੋਂ type recurse ਕਰਦਾ ਹੈ ਤਾਂ ਘਟਦਾ ਹੈ। ਜਦੋਂ counter ਜ਼ੀਰੋ 'ਤੇ ਪਹੁੰਚਦਾ ਹੈ, ਤਾਂ type ਅੱਗੇ ਜਾਣ ਦੀ ਬਜਾਏ string ਵਰਗਾ ਇੱਕ broad fallback ਰਿਟਰਨ ਕਰਦਾ ਹੈ। ਉਪਭੋਗਤਾਵਾਂ ਨੂੰ ਅਜੇ ਵੀ ਪਹਿਲੇ ਚਾਰ ਜਾਂ ਪੰਜ ਪੱਧਰਾਂ ਲਈ ਸਹੀ autocomplete ਮਿਲਦਾ ਹੈ, ਜੋ ਕਿ ਅਸਲ ਦੁਨੀਆ ਦੇ ਜ਼ਿਆਦਾਤਰ objects ਨੂੰ ਕਵਰ ਕਰਦਾ ਹੈ। ਉਸ ਤੋਂ ਬਾਅਦ, compiler ਸਿਰਫ਼ type ਨੂੰ ਵਧਾ ਦਿੰਦਾ ਹੈ ਅਤੇ ਅੱਗੇ ਵਧ ਜਾਂਦਾ ਹੈ।

ਇਹ ਤਰੀਕਾ ਤੁਹਾਡੇ utility type ਨੂੰ ਕਿਸੇ ਵੀ ਮਹੱਤਵਪੂਰਨ ਤਰੀਕੇ ਨਾਲ ਘੱਟ ਸਹੀ ਨਹੀਂ ਬਣਾਉਂਦਾ। ਇਹ ਇਸਨੂੰ ਸੀਮਤ (bounded) ਬਣਾਉਂਦਾ ਹੈ। ਇੱਕ type system ਜੋ compiler ਨੂੰ crash ਕਰ ਦਿੰਦਾ ਹੈ, ਉਹ ਉਸ ਤੋਂ ਵਧੇਰੇ ਉਪਯੋਗੀ ਨਹੀਂ ਹੈ ਜੋ ਇੱਕ ਵਾਜਬ ਡੂੰਘਾਈ ਤੋਂ ਬਾਅਦ ਸ਼ਾਂਤੀ ਨਾਲ ਹਾਰ ਮੰਨ ਲੈਂਦਾ ਹੈ।

Fix Two: ਇੱਕ ਸਮੇਂ ਵਿੱਚ ਇੱਕ ਹੀ Path ਨੂੰ ਵੈਲੀਡੇਟ ਕਰੋ

ਜੇਕਰ ਸ਼ੁਰੂ ਵਿੱਚ ਹੀ ਹਰ ਸੰਭਵ path ਬਣਾਉਣਾ ਬਹੁਤ ਮਹਿੰਗਾ ਹੈ, ਤਾਂ contract ਨੂੰ ਬਦਲ ਦਿਓ। ਸਾਰੇ ਵੈਲਿਡ strings ਦਾ ਇੱਕ ਵਿਸ਼ਾਲ union ਬਣਾਉਣ ਦੀ ਬਜਾਏ, ਇੱਕ ਅਜਿਹਾ type ਲਿਖੋ ਜੋ ਇਹ ਚੈੱਕ ਕਰੇ ਕਿ ਕੀ ਕੋਈ ਇੱਕ ਖਾਸ string ਇੱਕ ਵੈਲਿਡ path ਹੈ।

ਹਰ ਅੰਗਰੇਜ਼ੀ ਸ਼ਬਦ ਦੀ ਡਿਕਸ਼ਨਰੀ ਬਣਾਉਣ ਅਤੇ ਇਹ ਚੈੱਕ ਕਰਨ ਦੇ ਵਿਚਕਾਰਲੇ ਅੰਤਰ ਬਾਰੇ ਸੋਚੋ ਕਿ ਕੀ ਇੱਕ ਸ਼ਬਦ ਦੀ ਸਪੈਲਿੰਗ ਸਹੀ ਹੈ। ਪਹਿਲਾ ਇੱਕ ਬਹੁਤ ਵੱਡਾ data structure ਹੈ; ਦੂਜਾ ਇੱਕ ਹਲਕਾ (lightweight) ਸਕੈਨ ਹੈ। TypeScript ਦੇ ਸ਼ਬਦਾਂ ਵਿੱਚ, "user.address.street" | "user.settings.theme" | ... ਦੇਣ ਵਾਲਾ Paths<T> utility ਐਕਸਪੋਰਟ ਕਰਨ ਦੀ ਬਜਾਏ, ਤੁਸੀਂ IsValidPath<T, "user.address.street"> ਵਰਗੀ ਚੀਜ਼ ਐਕਸਪੋਰਟ ਕਰਦੇ ਹੋ। Compiler ਸਿਰਫ਼ ਉਸੇ path ਦੀ ਗਣਨਾ ਕਰਦਾ ਹੈ ਜੋ ਤੁਸੀਂ ਅਸਲ ਵਿੱਚ ਪਾਸ ਕਰਦੇ ਹੋ।

ਇਹ ਤਬਦੀਲੀ ਤੁਹਾਡੇ API ਡਿਜ਼ਾਈਨ ਕਰਨ ਦੇ ਤਰੀਕੇ ਨੂੰ ਬਦਲ ਦਿੰਦੀ ਹੈ। ਤੁਹਾਡੇ function signatures ਇੱਕ string ਸਵੀਕਾਰ ਕਰ ਸਕਦੇ ਹਨ ਅਤੇ ਫਿਰ object shape ਦੇ ਵਿਰੁੱਧ ਇਸਦੀ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਇੱਕ generic constraint ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੇ ਹਨ। ਜੇਕਰ ਡਿਵੈਲਪਰ ਗਲਤ path ਲਿਖਦਾ ਹੈ ਤਾਂ IDE ਅਜੇ ਵੀ ਸ਼ਿਕਾਇਤ ਕਰੇਗਾ, ਪਰ compiler ਨੂੰ type-checking ਦੌਰਾਨ ਕਾਨੂੰਨੀ paths ਦੇ ਪੂਰੇ ਸੈੱਟ ਨੂੰ ਬਣਾਉਣ ਦੀ ਲੋੜ ਨਹੀਂ ਪਵੇਗੀ। ਵੱਡੇ objects ਲਈ, performance ਦਾ ਅੰਤਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਹੁੰਦਾ ਹੈ।

Quick Tactics That Keep You Moving

ਦੋ structural fixes ਤੋਂ ਇਲਾਵਾ, ਕੁਝ ਛੋਟੀਆਂ ਆਦਤਾਂ recursive types ਨੂੰ ਸੀਮਾ ਤੋਂ ਬਾਹਰ ਜਾਣ ਤੋਂ ਰੋਕ ਸਕਦੀਆਂ ਹਨ:

  • ਡਿਸਟ੍ਰੀਬਿਊਸ਼ਨ (distribution) ਨੂੰ ਰੋਕਣ ਲਈ ਟਾਈਪ ਪੈਰਾਮੀਟਰਾਂ ਨੂੰ ਟੂਪਲਜ਼ (tuples) ਵਿੱਚ ਲਪੇਟੋ। ਇੱਕ ਕੰਡੀਸ਼ਨਲ ਵਿੱਚ ਇੱਕ ਨੰਗਾ (naked) ਟਾਈਪ ਪੈਰਾਮੀਟਰ, ਜਿਵੇਂ ਕਿ T extends Foo ? Bar : Baz, ਜਦੋਂ T ਇੱਕ ਯੂਨੀਅਨ (union) ਹੁੰਦਾ ਹੈ ਤਾਂ ਚੈੱਕ ਨੂੰ ਹਰ ਮੈਂਬਰ ਵਿੱਚ ਵੰਡ ਦਿੰਦਾ ਹੈ। ਜੇਕਰ ਉਸ ਯੂਨੀਅਨ ਵਿੱਚ ਪੰਜਾਹ ਮੈਂਬਰ ਹਨ, ਤਾਂ TypeScript ਪੰਜਾਹ ਵੱਖ-ਵੱਖ ਇੰਸਟੈਂਸ਼ੀਏਸ਼ਨਾਂ (instantiations) ਕਰਦਾ ਹੈ। [T] extends [Foo] ? Bar : Baz ਲਿਖਣ ਨਾਲ ਕੰਡੀਸ਼ਨਲ ਨੂੰ ਪੂਰੀ ਯੂਨੀਅਨ ਦੇ ਵਿਰੁੱਧ ਇੱਕ ਵਾਰ ਹੀ ਮਾਪਿਆ (evaluate) ਜਾਂਦਾ ਹੈ। ਇਸਦੀ ਵਰਤੋਂ ਉਦੋਂ ਕਰੋ ਜਦੋਂ ਤੁਹਾਨੂੰ ਅਸਲ ਵਿੱਚ ਟਾਈਪ ਨੂੰ ਹਰੇਕ ਯੂਨੀਅਨ ਮੈਂਬਰ ਉੱਤੇ ਵਿਅਕਤੀਗਤ ਤੌਰ 'ਤੇ ਮੈਪ ਕਰਨ ਦੀ ਲੋੜ ਨਾ ਹੋਵੇ।

  • ਡੀਬੱਗਿੰਗ ਕਰਦੇ ਸਮੇਂ ਆਪਣੇ ਇਨਪੁੱਟਸ ਨੂੰ ਘਟਾਓ। ਜਦੋਂ TS2589 ਦਿਖਾਈ ਦਿੰਦਾ ਹੈ, ਤਾਂ ਆਪਣੇ ਪ੍ਰੋਡਕਸ਼ਨ ਆਬਜੈਕਟ ਟਾਈਪ ਨੂੰ ਦੋ ਪ੍ਰੋਪਰਟੀਜ਼ ਅਤੇ ਇੱਕ ਲੈਵਲ ਦੀ ਨੇਸਟਿੰਗ (nesting) ਵਾਲੇ ਇੱਕ ਛੋਟੇ ਸਟੱਬ (stub) ਨਾਲ ਬਦਲ ਦਿਓ। ਜੇਕਰ ਗਲਤੀ ਦੂਰ ਹੋ ਜਾਂਦੀ ਹੈ, ਤਾਂ ਤੁਸੀਂ ਪੁਸ਼ਟੀ ਕਰ ਲਈ ਹੈ ਕਿ ਡੂੰਘਾਈ (depth) ਜਾਂ ਕਾਰਡੀਨੈਲਿਟੀ (cardinality) ਸਮੱਸਿਆ ਹੈ, ਕੋਈ ਸਿੰਟੈਕਸ ਗਲਤੀ ਨਹੀਂ। ਇਹ ਤੁਹਾਨੂੰ ਉਸ ਲੌਜਿਕ ਨੂੰ ਦੁਬਾਰਾ ਲਿਖਣ ਤੋਂ ਬਚਾਉਂਦਾ ਹੈ ਜੋ ਅਸਲ ਵਿੱਚ ਸੰਰਚਨਾਤਮਕ ਤੌਰ 'ਤੇ ਠੀਕ ਸੀ।

  • ਪਬਲਿਕ-ਫੇਸਿੰਗ API ਟਾਈਪਸ ਨੂੰ ਥੋੜਾ ਲਚਕੀਲਾ ਬਣਾਓ। ਅੰਦਰੂਨੀ ਤੌਰ 'ਤੇ, ਤੁਹਾਨੂੰ ਬਹੁਤ ਸਹੀ (surgical precision) ਹੋਣ ਦੀ ਲੋੜ ਹੋ ਸਕਦੀ ਹੈ। ਬਾਹਰੀ ਤੌਰ 'ਤੇ, ਕਦੇ-ਕਦੇ ਸੰਪੂਰਨਤਾ (perfection) ਦਾ ਮੁੱਲ ਉਸਦੇ ਫਾਇਦੇ ਨਾਲੋਂ ਜ਼ਿਆਦਾ ਹੁੰਦਾ ਹੈ। ਜੇਕਰ ਇੱਕ ਥੋੜਾ ਜਿਹਾ ਵਿਸ਼ਾਲ ਆਟੋ-ਕੰਪਲੀਟ (autocomplete) ਟਾਈਪ ਐਡੀਟਰ ਵਿੱਚ ਦੋ-ਸਕਿੰਟ ਦੇ ਲੈਗ (lag) ਨੂੰ ਰੋਕਦਾ ਹੈ, ਤਾਂ ਇਹ ਸੌਦਾ ਆਮ ਤੌਰ 'ਤੇ ਫਾਇਦੇਮੰਦ ਹੁੰਦਾ ਹੈ। ਤੁਸੀਂ ਟੈਸਟਿੰਗ ਵਿੱਚ ਗਲਤ ਪਾਥਾਂ ਨੂੰ ਫੜਨ ਲਈ ਲਚਕੀਲੇ ਟਾਈਪ ਨੂੰ ਰਨਟਾਈਮ ਵੈਲੀਡੇਟਰ (runtime validator) ਨਾਲ ਜੋੜ ਸਕਦੇ ਹੋ।

TypeScript ਇਸ ਸੀਮਾ ਨੂੰ ਕਿਉਂ ਲਾਗੂ ਕਰਦਾ ਹੈ

TypeScript 'halting problem' ਨੂੰ ਹੱਲ ਨਹੀਂ ਕਰ ਸਕਦਾ। ਇਸਨੂੰ ਇਹ ਨਹੀਂ ਪਤਾ ਹੁੰਦਾ ਕਿ ਤੁਹਾਡਾ ਰੀਕਰਸਿਵ (recursive) ਟਾਈਪ ਅੰਤ ਵਿੱਚ ਖਤਮ ਹੋਵੇਗਾ ਜਾਂ ਹਮੇਸ਼ਾ ਲਈ ਚਲਦਾ ਰਹੇਗਾ। ਕੰਪਾਈਲਰ ਦੇ ਅੰਦਰ ਇਨਫੀਨੀਟ ਲੂਪ (infinite loop) ਦਾ ਖਤਰਾ ਲੈਣ ਦੀ ਬਜਾਏ, ਇਹ ਇੱਕ ਸਾਵਧਾਨੀਪੂਰਨ ਕੱਟ-ਆਫ (cutoff) ਲਾਗੂ ਕਰਦਾ ਹੈ। ਕਦੇ-ਕਦੇ ਉਹ ਕੱਟ-ਆਫ ਅਜਿਹੇ ਟਾਈਪ ਨੂੰ ਰੋਕ ਲੈਂਦਾ ਹੈ ਜੋ ਕਾਫ਼ੀ ਸਮਾਂ ਮਿਲਣ 'ਤੇ ਖਤਮ ਹੋ ਸਕਦਾ ਸੀ। TS2589 ਕੰਪਾਈਲਰ ਦਾ ਇਹ ਮੰਨਣਾ ਹੈ ਕਿ ਉਹ ਗਲਤੀ ਹੋਣ ਦੇ ਡਰ ਨਾਲ ਸੁਰੱਖਿਅਤ ਰਹਿਣਾ ਪਸੰਦ ਕਰਦਾ ਹੈ।

ਉਸ ਸੀਮਾ ਦਾ ਸਤਿਕਾਰ ਕਰਨਾ ਪ੍ਰੋਡਕਸ਼ਨ-ਗ੍ਰੇਡ ਟਾਈਪਸ ਲਿਖਣ ਦਾ ਹਿੱਸਾ ਹੈ। ਇੱਕ ਟਾਈਪ ਡੈਫੀਨੇਸ਼ਨ ਉਹ ਕੋਡ ਹੈ ਜੋ ਕੰਪਾਈਲਰ ਵਿੱਚ ਚਲਦਾ ਹੈ, ਅਤੇ ਮਹਿੰਗੇ (expensive) ਕੋਡ ਦੇ ਅਸਲ ਨਤੀਜੇ ਹੁੰਦੇ ਹਨ। ਹੌਲੀ ਆਟੋ-ਕੰਪਲੀਟ ਡਿਵੈਲਪਰ ਦੀ ਗਤੀ (velocity) ਨੂੰ ਉਨਾ ਹੀ ਨੁਕਸਾਨ ਪਹੁੰਚਾਉਂਦਾ ਹੈ ਜਿੰਨਾ ਹੌਲੀ ਰਨਟਾਈਮ ਕੋਡ ਯੂਜ਼ਰ ਐਕਸਪੀਰੀਅੰਸ (user experience) ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚਾਉਂਦਾ ਹੈ।

ਅਸਲ ਸਿੱਖਿਆ

TS2589 ਇਸ ਗੱਲ ਦਾ ਸੰਕੇਤ ਨਹੀਂ ਹੈ ਕਿ ਤੁਸੀਂ ਇੱਕ ਮਾੜੇ ਟਾਈਪ-ਸਿਸਟਮ ਪ੍ਰੋਗਰਾਮਰ ਹੋ। ਇਹ ਇਸ ਗੱਲ ਦਾ ਸੰਕੇਤ ਹੈ ਕਿ ਤੁਹਾਡਾ ਟਾਈਪ ਇੱਕੋ ਸਮੇਂ ਬਹੁਤ ਜ਼ਿਆਦਾ ਕੰਮ ਕਰ ਰਿਹਾ ਹੈ। ਆਪਣੀ ਰੀਕਰਸ਼ਨ (recursion) ਨੂੰ ਸੀਮਤ ਕਰੋ, ਲੇਜ਼ੀ ਵੈਲੀਡੇਸ਼ਨ (lazy validation) ਕਰੋ, ਅਤੇ ਬੇਲੋੜੀ ਡਿਸਟ੍ਰੀਬਿਊਸ਼ਨ ਤੋਂ ਬਚੋ। ਐਡਵਾਂਸਡ ਟਾਈਪਸ ਦਾ ਉਦੇਸ਼ ਕੰਪਾਈਲ ਟਾਈਮ 'ਤੇ ਹਰ ਸੰਭਵ ਸੱਚ ਨੂੰ ਸਾਬਤ ਕਰਨਾ ਨਹੀਂ ਹੈ; ਇਸਦਾ ਉਦੇਸ਼ ਤੁਹਾਡੀ ਟੀਮ ਨੂੰ ਤੇਜ਼ ਅਤੇ ਭਰੋਸੇਯੋਗ ਟੂਲਿੰਗ (tooling) ਦੇਣਾ ਹੈ। ਇੱਕ ਟਾਈਪ ਜੋ ਮਿਲੀਸਕਿੰਡਾਂ ਵਿੱਚ ਕੰਪਾਈਲ ਹੁੰਦਾ ਹੈ ਅਤੇ ਨੜਿਨਵੇਂ ਫੀਸਦੀ (95%) ਕੇਸਾਂ ਨੂੰ ਕਵਰ ਕਰਦਾ ਹੈ, ਉਹ ਉਸ ਟਾਈਪ ਨਾਲੋਂ ਕਿਤੇ ਜ਼ਿਆਦਾ ਕੀਮਤੀ ਹੈ ਜੋ ਸਿਧਾਂਤਕ ਤੌਰ 'ਤੇ ਸੰਪੂਰਨ ਹੈ ਪਰ ਲੈਂਗੂਏਜ ਸਰਵਰ (language server) ਨੂੰ ਕ੍ਰੈਸ਼ ਕਰ ਦਿੰਦਾ ਹੈ।