├── .gitignore ├── .prettierrc.json ├── README.md ├── errors └── includes │ ├── TS17xxx │ ├── TS17000.md │ ├── TS17004.md │ └── TS17009.md │ ├── TS18xxx │ ├── TS18004.md │ ├── TS18016.md │ ├── TS18046.md │ └── TS18048.md │ ├── TS1xxx │ ├── TS1002.md │ ├── TS1005.md │ ├── TS1006.md │ ├── TS1015.md │ ├── TS1016.md │ ├── TS1029.md │ ├── TS1036.md │ ├── TS1038.md │ ├── TS1039.md │ ├── TS1046.md │ ├── TS1055.md │ ├── TS1056.md │ ├── TS1064.md │ ├── TS1066.md │ ├── TS1068.md │ ├── TS1070.md │ ├── TS1095.md │ ├── TS1103.md │ ├── TS1109.md │ ├── TS1117.md │ ├── TS1127.md │ ├── TS1128.md │ ├── TS1149.md │ ├── TS1155.md │ ├── TS1160.md │ ├── TS1183.md │ ├── TS1192.md │ ├── TS1196.md │ ├── TS1202.md │ ├── TS1208.md │ ├── TS1218.md │ ├── TS1219.md │ ├── TS1225.md │ ├── TS1228.md │ ├── TS1243.md │ ├── TS1244.md │ ├── TS1254.md │ ├── TS1259.md │ ├── TS1308.md │ ├── TS1337.md │ ├── TS1341.md │ ├── TS1355.md │ ├── TS1357.md │ ├── TS1361.md │ ├── TS1363.md │ ├── TS1368.md │ ├── TS1371.md │ ├── TS1375.md │ ├── TS1378.md │ ├── TS1385.md │ ├── TS1389.md │ ├── TS1431.md │ ├── TS1432.md │ ├── TS1434.md │ └── TS1471.md │ ├── TS2xxx │ ├── TS2300.md │ ├── TS2304.md │ ├── TS2305.md │ ├── TS2306.md │ ├── TS2307.md │ ├── TS2314.md │ ├── TS2315.md │ ├── TS2322.md │ ├── TS2335.md │ ├── TS2339.md │ ├── TS2344.md │ ├── TS2345.md │ ├── TS2348.md │ ├── TS2349.md │ ├── TS2351.md │ ├── TS2352.md │ ├── TS2355.md │ ├── TS2361.md │ ├── TS2362.md │ ├── TS2364.md │ ├── TS2365.md │ ├── TS2366.md │ ├── TS2367.md │ ├── TS2368.md │ ├── TS2369.md │ ├── TS2370.md │ ├── TS2371.md │ ├── TS2372.md │ ├── TS2377.md │ ├── TS2378.md │ ├── TS2390.md │ ├── TS2391.md │ ├── TS2394.md │ ├── TS2395.md │ ├── TS2403.md │ ├── TS2411.md │ ├── TS2420.md │ ├── TS2428.md │ ├── TS2430.md │ ├── TS2440.md │ ├── TS2445.md │ ├── TS2448.md │ ├── TS2451.md │ ├── TS2454.md │ ├── TS2456.md │ ├── TS2459.md │ ├── TS2475.md │ ├── TS2476.md │ ├── TS2488.md │ ├── TS2497.md │ ├── TS2503.md │ ├── TS2507.md │ ├── TS2511.md │ ├── TS2512.md │ ├── TS2515.md │ ├── TS2528.md │ ├── TS2531.md │ ├── TS2532.md │ ├── TS2533.md │ ├── TS2538.md │ ├── TS2540.md │ ├── TS2550.md │ ├── TS2551.md │ ├── TS2552.md │ ├── TS2554.md │ ├── TS2556.md │ ├── TS2558.md │ ├── TS2559.md │ ├── TS2564.md │ ├── TS2567.md │ ├── TS2571.md │ ├── TS2574.md │ ├── TS2577.md │ ├── TS2580.md │ ├── TS2582.md │ ├── TS2583.md │ ├── TS2584.md │ ├── TS2588.md │ ├── TS2595.md │ ├── TS2611.md │ ├── TS2613.md │ ├── TS2616.md │ ├── TS2636.md │ ├── TS2637.md │ ├── TS2652.md │ ├── TS2654.md │ ├── TS2656.md │ ├── TS2661.md │ ├── TS2663.md │ ├── TS2664.md │ ├── TS2665.md │ ├── TS2668.md │ ├── TS2669.md │ ├── TS2677.md │ ├── TS2678.md │ ├── TS2680.md │ ├── TS2683.md │ ├── TS2684.md │ ├── TS2686.md │ ├── TS2687.md │ ├── TS2689.md │ ├── TS2691.md │ ├── TS2693.md │ ├── TS2694.md │ ├── TS2695.md │ ├── TS2706.md │ ├── TS2709.md │ ├── TS2713.md │ ├── TS2715.md │ ├── TS2717.md │ ├── TS2720.md │ ├── TS2722.md │ ├── TS2724.md │ ├── TS2730.md │ ├── TS2732.md │ ├── TS2739.md │ ├── TS2740.md │ ├── TS2741.md │ ├── TS2742.md │ ├── TS2749.md │ ├── TS2769.md │ ├── TS2774.md │ ├── TS2779.md │ ├── TS2786.md │ ├── TS2790.md │ ├── TS2792.md │ ├── TS2794.md │ ├── TS2813.md │ └── TS2814.md │ ├── TS4xxx │ ├── TS4020.md │ ├── TS4025.md │ ├── TS4060.md │ ├── TS4063.md │ ├── TS4075.md │ ├── TS4081.md │ ├── TS4104.md │ ├── TS4112.md │ ├── TS4113.md │ └── TS4114.md │ ├── TS5xxx │ ├── TS5023.md │ ├── TS5024.md │ ├── TS5025.md │ ├── TS5042.md │ ├── TS5054.md │ ├── TS5055.md │ ├── TS5058.md │ ├── TS5069.md │ ├── TS5070.md │ ├── TS5083.md │ ├── TS5087.md │ └── TS5101.md │ ├── TS6xxx │ ├── TS6053.md │ ├── TS6059.md │ ├── TS6133.md │ ├── TS6138.md │ ├── TS6196.md │ ├── TS6198.md │ └── TS6504.md │ ├── TS7xxx │ ├── TS7006.md │ ├── TS7008.md │ ├── TS7009.md │ ├── TS7010.md │ ├── TS7016.md │ ├── TS7017.md │ ├── TS7022.md │ ├── TS7023.md │ ├── TS7026.md │ ├── TS7027.md │ ├── TS7030.md │ ├── TS7031.md │ ├── TS7034.md │ ├── TS7041.md │ ├── TS7044.md │ └── TS7053.md │ ├── TS80xxx │ └── TS80005.md │ └── TS8xxx │ └── TS8020.md ├── lefthook.yml ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/prettierrc", 3 | "arrowParens": "avoid", 4 | "bracketSameLine": false, 5 | "bracketSpacing": false, 6 | "endOfLine": "lf", 7 | "printWidth": 120, 8 | "proseWrap": "never", 9 | "requirePragma": false, 10 | "semi": true, 11 | "singleAttributePerLine": true, 12 | "singleQuote": true, 13 | "tabWidth": 2, 14 | "trailingComma": "es5", 15 | "useTabs": false 16 | } 17 | -------------------------------------------------------------------------------- /errors/includes/TS17xxx/TS17000.md: -------------------------------------------------------------------------------- 1 | ## TS17000 2 | 3 | > error TS17000: JSX attributes must only be assigned a non-empty 'expression'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```tsx 8 | Title 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | You can't use an empty expression (`{}`) in JSX attributes: 14 | 15 | ```tsx 16 | Title 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS17xxx/TS17004.md: -------------------------------------------------------------------------------- 1 | ## TS17004 2 | 3 | > error TS17004: Cannot use JSX unless the '--jsx' flag is provided. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```tsx 8 | function App() { 9 | return

My App!

; 10 | } 11 | 12 | export default App; 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | You have to add a configuration for "jsx" to your "tsconfig.json" file: 18 | 19 | 20 | {% codeblock lang:json tsconfig.json %} 21 | { 22 | "compilerOptions": { 23 | "jsx": "react" 24 | } 25 | } 26 | {% endcodeblock %} 27 | 28 | -------------------------------------------------------------------------------- /errors/includes/TS17xxx/TS17009.md: -------------------------------------------------------------------------------- 1 | ## TS17009 2 | 3 | > error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | abstract class Animal { 9 | abstract name: string; 10 | } 11 | 12 | class Dog extends Animal { 13 | public name; 14 | 15 | constructor(name: string) { 16 | this.name = name; 17 | super(); 18 | } 19 | } 20 | ``` 21 | 22 | ### Fixed Code ✔️ 23 | 24 | 25 | {% codeblock lang:ts mark:9 %} 26 | abstract class Animal { 27 | abstract name: string; 28 | } 29 | 30 | class Dog extends Animal { 31 | public name; 32 | 33 | constructor(name: string) { 34 | super(); 35 | this.name = name; 36 | } 37 | } 38 | {% endcodeblock %} 39 | 40 | -------------------------------------------------------------------------------- /errors/includes/TS18xxx/TS18004.md: -------------------------------------------------------------------------------- 1 | ## TS18004 2 | 3 | > error TS18004: No value exists in scope for the shorthand property '`age`'. Either declare one or provide an initializer. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export function getPerson() { 9 | return { 10 | age, 11 | fistName: 'Benny', 12 | lastName: 'Neugebauer', 13 | }; 14 | } 15 | ``` 16 | 17 | ### Fixed Code ✔️ 18 | 19 | If you want to use the **shorthand property name syntax** to access the `age` property, you have to make sure that this variable is defined in the first place: 20 | 21 | ```ts 22 | export function getPerson() { 23 | const age = 34; 24 | return { 25 | age, 26 | fistName: 'Benny', 27 | lastName: 'Neugebauer', 28 | }; 29 | } 30 | ``` 31 | 32 | Alternatively, you can avoid using the **shorthand property name syntax**: 33 | 34 | ```ts 35 | export function getPerson() { 36 | return { 37 | age: 34, 38 | fistName: 'Benny', 39 | lastName: 'Neugebauer', 40 | }; 41 | } 42 | ``` 43 | -------------------------------------------------------------------------------- /errors/includes/TS18xxx/TS18016.md: -------------------------------------------------------------------------------- 1 | ## TS18016 2 | 3 | > error TS18016: Private identifiers are not allowed outside class bodies. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | interface Person { 9 | #age: number; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | Private properties can only be used in classes but not in interfaces. We therefore need to convert the interface into a class in order to be able to compile the code: 16 | 17 | ```ts 18 | class Person { 19 | #age: number; 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS18xxx/TS18046.md: -------------------------------------------------------------------------------- 1 | ## TS18046 2 | 3 | > error TS18046: '`error`' is of type '`unknown`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock mark:5 %} 9 | async function test() { 10 | try { 11 | await Promise.reject(new Error('This is a test')); 12 | } catch (error: unknown) { 13 | console.error(error.message); 14 | } 15 | } 16 | 17 | test(); 18 | {% endcodeblock %} 19 | 20 | 21 | ### Fixed Code ✔️ 22 | 23 | If you set the `useUnknownInCatchVariables` option to `true` in your `tsconfig.json` file, you may encounter the **TS18046** error. 24 | 25 | Enabling the [useUnknownInCatchVariables](https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables) feature causes the error within a catch clause to be treated as the `unknown` type instead of `any`. As a result, you will need to incorporate a [type guard](/glossary/index.html#Type-Guards) or an [assertion function](/glossary/index.html#Assertion-Functions) to access properties on an object of type `unknown`: 26 | 27 | ```ts 28 | async function test() { 29 | try { 30 | await Promise.reject(new Error('This is a test')); 31 | } catch (error: unknown) { 32 | if (error instanceof Error) { 33 | console.error(error.message); 34 | } 35 | } 36 | } 37 | 38 | test(); 39 | ``` 40 | -------------------------------------------------------------------------------- /errors/includes/TS18xxx/TS18048.md: -------------------------------------------------------------------------------- 1 | ## TS18048 2 | 3 | > error TS18048: '`text`' is possibly '`undefined`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function getShortenedText(text?: string): string { 9 | return text.slice(0, 5); 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | If the `text` parameter is optional, it can potentially be of type `unknown`. When the type is `unknown`, accessing methods like [Array.slice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice) is not possible. 16 | 17 | To solve this error, we need to employ a [type guard](/glossary/index.html#Type-Guards) to ensure that `text` is of type `string`: 18 | 19 | ```ts 20 | function getShortenedText(text?: string): string { 21 | if (typeof text === 'string') { 22 | return text.slice(0, 5); 23 | } 24 | return ''; 25 | } 26 | ``` 27 | 28 | **Note:** We also need to employ a default return value to maintain the function return type of `string`. 29 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1002.md: -------------------------------------------------------------------------------- 1 | ## TS1002 2 | 3 | > error TS1002: Unterminated string literal. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const text = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | You have to close the **string literal** with an ending `'`: 14 | 15 | ```ts 16 | const text = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr'; 17 | ``` 18 | 19 | If you want to support multiline text, then you would have to use **string concatenation**: 20 | 21 | ```ts 22 | const text = 23 | 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, ' + 24 | 'sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.'; 25 | ``` 26 | 27 | Another solution would be using a **[template literal](/glossary/index.html#Template-Literal)**: 28 | 29 | ```ts 30 | const text = `Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 31 | sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.`; 32 | ``` 33 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1005.md: -------------------------------------------------------------------------------- 1 | ## TS1005 2 | 3 | > error TS1005: '=' expected. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type Person { 9 | age: number; 10 | name: string; 11 | } 12 | ``` 13 | 14 | ### Fixed Code ✔️ 15 | 16 | You need to assign your type declaration using the `=` character: 17 | 18 | ```ts 19 | type Person = { 20 | age: number; 21 | name: string; 22 | }; 23 | ``` 24 | 25 | Alternatively you can declare an interface: 26 | 27 | ```ts 28 | interface Person { 29 | age: number; 30 | name: string; 31 | } 32 | ``` 33 | 34 | > error TS1005: ';' expected. 35 | 36 | ### Broken Code ❌ 37 | 38 | ```ts 39 | export function getNumbers(names: string[]) { 40 | return names.map(name => {[name]: parseInt(name)}); 41 | } 42 | ``` 43 | 44 | ### Fixed Code ✔️ 45 | 46 | When using an [**arrow function expression**](/glossary/index.html#Arrow-Function-Expression), you can implicitly return values by wrapping the [**object literal**](/glossary/index.html#Literal-Types) in parentheses: 47 | 48 | 49 | {% codeblock lang:ts mark:2 %} 50 | export function getNumbers(names: string[]) { 51 | return names.map(name => ({[name]: parseInt(name)})); 52 | } 53 | {% endcodeblock %} 54 | 55 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1006.md: -------------------------------------------------------------------------------- 1 | ## TS1006 2 | 3 | > error TS1006: A file cannot have a reference to itself. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock index.d.ts lang:ts %} 9 | /// 10 | {% endcodeblock %} 11 | 12 | 13 | ### Fixed Code ✔️ 14 | 15 | You cannot reference a file to itself (causes recursive loop). To fix the problem you have to update the reference path to point to another **declaration file**: 16 | 17 | 18 | {% codeblock index.d.ts lang:ts %} 19 | /// 20 | {% endcodeblock %} 21 | 22 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1015.md: -------------------------------------------------------------------------------- 1 | ## TS1015 2 | 3 | > error TS1015: Parameter cannot have question mark and initializer. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export function getName(firstName: string, lastName?: string = 'Doe'): string { 9 | return `${firstName} ${lastName}`; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | ```ts 16 | export function getName(firstName: string, lastName: string = 'Doe'): string { 17 | return `${firstName} ${lastName}`; 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1016.md: -------------------------------------------------------------------------------- 1 | ## TS1016 2 | 3 | > error TS1016: A required parameter cannot follow an optional parameter. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function createUser(firstName: string, lastName: string, middleName?: string, age: number) { 9 | // ... 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | The easiest way to fix the error is to make `age` optional as well: 16 | 17 | ```ts 18 | function createUser(firstName: string, lastName: string, middleName?: string, age?: number) { 19 | // ... 20 | } 21 | ``` 22 | 23 | Alternatively, you can flip the order of `middleName` and `age`. Be aware that this breaks the contract (signature) of the function and is considered a "breaking change": 24 | 25 | ```ts 26 | function createUser(firstName: string, lastName: string, age: number, middleName?: string) { 27 | // ... 28 | } 29 | ``` 30 | 31 | You could also make `middleName` non-optional: 32 | 33 | ```ts 34 | function createUser(firstName: string, lastName: string, middleName: string, age?: number) { 35 | // ... 36 | } 37 | ``` 38 | 39 | Yet another solution would be to assign a default value to `middleName` so it won't be optional by default. This allows `age` to be optional then: 40 | 41 | ```ts 42 | function createUser(firstName: string, lastName: string, middleName: string = '', age?: number) { 43 | // ... 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1029.md: -------------------------------------------------------------------------------- 1 | ## TS1029 2 | 3 | > error TS1029: 'public' modifier must precede 'abstract' modifier. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | ```ts 9 | abstract class Animal { 10 | abstract public makeNoise(): string; 11 | } 12 | ``` 13 | 14 | 15 | ### Fixed Code ✔️ 16 | 17 | They keywords `public`, `private`, and `protected` define the access to a class member. Access modifiers have to be defined first in TypeScript. 18 | 19 | Solution 1: 20 | 21 | 22 | ```ts 23 | abstract class Animal { 24 | public abstract makeNoise(): string; 25 | } 26 | ``` 27 | 28 | 29 | Solution 2: 30 | 31 | The visibility is `public` by default, so you don't have to explicitly declare it: 32 | 33 | 34 | ```ts 35 | abstract class Animal { 36 | abstract makeNoise(): string; 37 | } 38 | ``` 39 | 40 | 41 | ### Video Tutorial 42 | 43 | {% youtube 62J_eQsK0e0?start=531 'video' false %} 44 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1036.md: -------------------------------------------------------------------------------- 1 | ## TS1036 2 | 3 | > error TS1036: Statements are not allowed in ambient contexts. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import {APIClient} from '../../APIClient'; 9 | 10 | declare global { 11 | client: APIClient; 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | With `declare global` an [ambient context](/glossary/index.html#Ambient-Context) is created. TypeScript does not allow statements in such ambient context declaration which is why we have to change the statement into a declaration: 18 | 19 | ```ts 20 | declare global { 21 | function client(): APIClient; 22 | } 23 | ``` 24 | 25 | If you don't want `client` to be a `function, you have to use the `var` keyword: 26 | 27 | ```ts 28 | declare global { 29 | var client: APIClient; 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1038.md: -------------------------------------------------------------------------------- 1 | ## TS1038 2 | 3 | > error TS1038: A 'declare' modifier cannot be used in an already ambient context. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | declare global { 9 | declare var REST_URL: string; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | ```ts 16 | declare global { 17 | var REST_URL: string; 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1039.md: -------------------------------------------------------------------------------- 1 | ## TS1039 2 | 3 | > error TS1039: Initializers are not allowed in ambient contexts. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock index.d.ts lang:ts %} 9 | declare module hexo { 10 | var config = { 11 | 12 | } 13 | } 14 | {% endcodeblock %} 15 | 16 | 17 | ### Fixed Code ✔️ 18 | 19 | Within a declaration file (ambient context), you should define types instead of implementing code. Consequently, you'll need to replace the initialization with a type annotation: 20 | 21 | 22 | {% codeblock index.d.ts lang:ts %} 23 | declare module hexo { 24 | var config: {}; 25 | } 26 | {% endcodeblock %} 27 | 28 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1046.md: -------------------------------------------------------------------------------- 1 | ## TS1046 2 | 3 | > error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock index.d.ts lang:ts %} 9 | const MAGIC_NUMBER = 1337; 10 | {% endcodeblock %} 11 | 12 | 13 | ### Fixed Code ✔️ 14 | 15 | If you want to export a constant from a definition file (`d.ts`), then you have to use the `export` modifier: 16 | 17 | 18 | {% codeblock index.d.ts lang:ts %} 19 | export const MAGIC_NUMBER = 1337; 20 | {% endcodeblock %} 21 | 22 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1055.md: -------------------------------------------------------------------------------- 1 | ## TS1055 2 | 3 | > error TS1055: Type '`AxiosPromise`' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts %} 9 | export const sendRequestWithCookie = async ( 10 | client: HttpClient, 11 | config: AxiosRequestConfig, 12 | engine: CRUDEngine 13 | ): AxiosPromise => { 14 | const cookie: Cookie = await loadExistingCookie(engine); 15 | 16 | if (!cookie.isExpired) { 17 | config.headers = config.headers || {}; 18 | config.headers['Cookie'] = `zuid=${cookie.zuid}`; 19 | config.withCredentials = true; 20 | } 21 | 22 | return client._sendRequest(config); 23 | }; 24 | {% endcodeblock %} 25 | 26 | 27 | ### Fixed Code ✔️ 28 | 29 | 30 | {% codeblock lang:ts mark:6,14 %} 31 | export const sendRequestWithCookie = ( 32 | client: HttpClient, 33 | config: AxiosRequestConfig, 34 | engine: CRUDEngine 35 | ): AxiosPromise => { 36 | return loadExistingCookie(engine).then((cookie: Cookie) => { 37 | if (!cookie.isExpired) { 38 | config.headers = config.headers || {}; 39 | config.headers['Cookie'] = `zuid=${cookie.zuid}`; 40 | config.withCredentials = true; 41 | } 42 | 43 | return client._sendRequest(config); 44 | }); 45 | }; 46 | {% endcodeblock %} 47 | 48 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1056.md: -------------------------------------------------------------------------------- 1 | ## TS1056 2 | 3 | > error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts User.ts %} 9 | class User { 10 | constructor(private firstName: string, private lastName: string) { 11 | } 12 | 13 | get fullName() { 14 | return `${this.firstName} ${this.lastName}`; 15 | } 16 | } 17 | {% endcodeblock %} 18 | 19 | 20 | 21 | {% codeblock lang:json tsconfig.json %} 22 | { 23 | "compilerOptions": { 24 | "target": "es3" 25 | } 26 | } 27 | {% endcodeblock %} 28 | 29 | 30 | ### Fixed Code ✔️ 31 | 32 | Set the "target" property in your "tsconfig.json" file to "es5" or higher: 33 | 34 | 35 | {% codeblock lang:json tsconfig.json mark:3 %} 36 | { 37 | "compilerOptions": { 38 | "target": "es5" 39 | } 40 | } 41 | {% endcodeblock %} 42 | 43 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1064.md: -------------------------------------------------------------------------------- 1 | ## TS1064 2 | 3 | > error TS1064: The return type of an async function or method must be the global Promise type. Did you mean to write 'Promise '? 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | async function myFunction(): string { 9 | return 'test'; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | If your function is asynchronous, your return value must be wrapped with `Promise<...>`: 16 | 17 | ```ts 18 | async function myFunction(): Promise { 19 | return 'test'; 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1066.md: -------------------------------------------------------------------------------- 1 | ## TS1066 2 | 3 | > error TS1066: In ambient enum declarations member initializer must be constant expression. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | enum PreKeyAuth { 9 | INVALID = 'Invalid', 10 | UNKNOWN = 'Unknown', 11 | VALID = 'Valid', 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | Try to replace your enum declaration with a type: 18 | 19 | ```ts 20 | type PreKeyAuth = 'Invalid' | 'Unknown' | 'Valid'; 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1068.md: -------------------------------------------------------------------------------- 1 | ## TS1068 2 | 3 | > error TS1068: Unexpected token. A constructor, method, accessor, or property was expected. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | class User { 9 | constructor(private firstName: string, private lastName: string) { 10 | } 11 | 12 | function getName() { 13 | return `${this.firstName} ${this.lastName}`; 14 | } 15 | } 16 | ``` 17 | 18 | ### Fixed Code ✔️ 19 | 20 | Functions that are part of a class are being called "method". The method of a class is defined without the `function` keyword: 21 | 22 | ```ts 23 | class User { 24 | constructor(private firstName: string, private lastName: string) {} 25 | 26 | getName() { 27 | return `${this.firstName} ${this.lastName}`; 28 | } 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1070.md: -------------------------------------------------------------------------------- 1 | ## TS1070 2 | 3 | > error TS1070: 'private' modifier cannot appear on a type member. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | ```ts 9 | interface Animal { 10 | private name: string; 11 | } 12 | ``` 13 | 14 | 15 | ### Fixed Code ✔️ 16 | 17 | Interfaces are structures that define the public contract. This prohibits you from using `private` modifiers. Only `public` and `protected` can be used. To solve the problem, the `private` keyword must be removed from the `name` property of the `Animal` interface: 18 | 19 | ```ts 20 | interface Animal { 21 | name: string; 22 | } 23 | ``` 24 | 25 | ### Video Tutorial 26 | 27 | {% youtube 62J_eQsK0e0?start=165 'video' false %} 28 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1095.md: -------------------------------------------------------------------------------- 1 | ## TS1095 2 | 3 | > error TS1095: A 'set' accessor cannot have a return type annotation. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts %} 9 | export class Person { 10 | private myName: string = 'unknown'; 11 | 12 | get name(): string { 13 | return this.myName; 14 | } 15 | 16 | set name(newName: string): void { 17 | this.myName = newName; 18 | } 19 | } 20 | {% endcodeblock %} 21 | 22 | 23 | ### Fixed Code ✔️ 24 | 25 | You have to remove the return type from the "set" accessor: 26 | 27 | 28 | {% codeblock lang:ts mark:8 %} 29 | export class Person { 30 | private myName: string = 'unknown'; 31 | 32 | get name(): string { 33 | return this.myName; 34 | } 35 | 36 | set name(newName: string) { 37 | this.myName = newName; 38 | } 39 | } 40 | {% endcodeblock %} 41 | 42 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1103.md: -------------------------------------------------------------------------------- 1 | ## TS1103 2 | 3 | > error TS1103: 'for await' loops are only allowed within async functions and at the top levels of modules. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import fs from 'node:fs'; 9 | import readline from 'node:readline'; 10 | 11 | const inputStream = fs.createReadStream('file.csv'); 12 | 13 | function printLine(file: string): Promise { 14 | const rl = readline.createInterface({ 15 | input: inputStream, 16 | crlfDelay: Infinity, 17 | }); 18 | 19 | for await (const line of rl) { 20 | console.log(line); 21 | } 22 | } 23 | ``` 24 | 25 | ### Fixed Code ✔️ 26 | 27 | You have to mark your function with the `async` keyword: 28 | 29 | ```ts 30 | import fs from 'node:fs'; 31 | import readline from 'node:readline'; 32 | 33 | const inputStream = fs.createReadStream('file.csv'); 34 | 35 | async function printLine(file: string): Promise { 36 | const rl = readline.createInterface({ 37 | input: inputStream, 38 | crlfDelay: Infinity, 39 | }); 40 | 41 | for await (const line of rl) { 42 | console.log(line); 43 | } 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1109.md: -------------------------------------------------------------------------------- 1 | ## TS1109 2 | 3 | > error TS1109: Expression expected. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const lastName = throw new Error('Missing last name'); 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | Any snippet of code that evaluates to a value is an **expression**. Any snippet of code that performs an action is a **statement**. We need a statement to throw an error inside: 14 | 15 | ```ts 16 | const lastName = undefined; 17 | if (!lastName) { 18 | throw new Error('Missing last name'); 19 | } 20 | ``` 21 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1117.md: -------------------------------------------------------------------------------- 1 | ## TS1117 2 | 3 | > error TS1117: An object literal cannot have multiple properties with the same name in strict mode. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const objectLiteral = { 9 | name: 'Benny', 10 | name: 'Sofia', 11 | }; 12 | ``` 13 | 14 | ### Fixed Code ✔️ 15 | 16 | We can only have one value per property: 17 | 18 | ```ts 19 | const objectLiteral = { 20 | name: 'Benny', 21 | }; 22 | ``` 23 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1127.md: -------------------------------------------------------------------------------- 1 | ## TS1127 2 | 3 | > error TS1127: Invalid character. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | # My comment 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | Unlike in Python, inline comments cannot begin with a single hash sign (`#`) in TypeScript. You must use 2 slashes: 14 | 15 | ```ts 16 | // My comment 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1128.md: -------------------------------------------------------------------------------- 1 | ## TS1128 2 | 3 | > error TS1128: Declaration or statement expected. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | = 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | A **declaration** specifies the data and a **statement** specifies some action with that data: 14 | 15 | ```ts 16 | // Declaration 17 | let MY_NUMBER = 1; 18 | // Statement 19 | MY_NUMBER = MY_NUMBER + 1; 20 | ``` 21 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1149.md: -------------------------------------------------------------------------------- 1 | ## TS1149 2 | 3 | > TS1149: File name differs from already included file name only in casing. 4 | 5 | ### Broken Code ❌ 6 | 7 | This error occurs when you import the same file in two different files using two different casing styles (ex. camelCase and UpperCamelCase): 8 | 9 | File A: 10 | 11 | ```ts 12 | import {BaseTestPage} from './baseTestPage'; 13 | ``` 14 | 15 | File B: 16 | 17 | ```ts 18 | import {BaseTestPage} from './BaseTestPage'; 19 | ``` 20 | 21 | ### Fixed Code ✔️ 22 | 23 | The error can be fixed by using the same casing style: 24 | 25 | **File A:** 26 | 27 | ```ts 28 | import {BaseTestPage} from './BaseTestPage'; 29 | ``` 30 | 31 | **File B:** 32 | 33 | ```ts 34 | import {BaseTestPage} from './BaseTestPage'; 35 | ``` 36 | 37 | Alternatively, you can set `forceConsistentCasingInFileNames` to `false` in your "tsconfig.json" file: 38 | 39 | 40 | {% codeblock lang:json tsconfig.json %} 41 | { 42 | "compilerOptions": { 43 | "forceConsistentCasingInFileNames": false 44 | } 45 | } 46 | {% endcodeblock %} 47 | 48 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1155.md: -------------------------------------------------------------------------------- 1 | ## TS1155 2 | 3 | > error TS1155: 'const' declarations must be initialized. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const name: string; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | ```ts 14 | const name: string = 'Benny'; 15 | ``` 16 | 17 | Alternatively you can define a block-scoped local variable: 18 | 19 | ```ts 20 | let name: string; 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1160.md: -------------------------------------------------------------------------------- 1 | ## TS1160 2 | 3 | > error TS1160: Unterminated template literal. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const text = `Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 9 | sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 10 | ``` 11 | 12 | ### Fixed Code ✔️ 13 | 14 | This error is similar to [TS1002](#TS1002) but refers to the ending of a [**template literal**](/glossary/index.html#Template-Literal). To fix it, we have to close the template literal with an ending `` ` ``: 15 | 16 | ```ts 17 | const text = `Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 18 | sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.`; 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1183.md: -------------------------------------------------------------------------------- 1 | ## TS1183 2 | 3 | > error TS1183: An implementation cannot be declared in ambient contexts. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock index.d.ts lang:ts %} 9 | export function logSomething(error: unknown): void { 10 | console.log('something'); 11 | } 12 | {% endcodeblock %} 13 | 14 | 15 | ### Fixed Code ✔️ 16 | 17 | You cannot write a **function implementation** inside a **declaration file** (`*.d.ts`). You can only declare its signature: 18 | 19 | 20 | {% codeblock index.d.ts lang:ts %} 21 | export function logSomething(error: unknown): void; 22 | {% endcodeblock %} 23 | 24 | 25 | Alternatively, you can write your function implementation inside a **source code file** (`*.ts`). 26 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1192.md: -------------------------------------------------------------------------------- 1 | ## TS1192 2 | 3 | > error TS1192: Module '`json5`' has no default export. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import json5 from 'json5'; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | When you are importing a module with built-in TypeScript declarations and TypeScript tells you that this module does not have a default export, then you can solve this problem by adding "allowSyntheticDefaultImports" to your "tsconfig.json" file and setting it to `true`: 14 | 15 | 16 | {% codeblock lang:json tsconfig.json %} 17 | { 18 | "compilerOptions": { 19 | "allowSyntheticDefaultImports": true 20 | } 21 | } 22 | {% endcodeblock %} 23 | 24 | 25 | > error TS1192: Module '`.../logdown`' has no default export. 26 | 27 | ### Broken Code ❌ 28 | 29 | 30 | {% codeblock lang:ts %} 31 | declare class Logdown { 32 | // ... 33 | } 34 | 35 | export = Logdown; 36 | {% endcodeblock %} 37 | 38 | 39 | ### Fixed Code ✔️ 40 | 41 | 42 | {% codeblock lang:ts mark:5 %} 43 | declare class Logdown { 44 | // ... 45 | } 46 | 47 | export default Logdown; 48 | {% endcodeblock %} 49 | 50 | 51 | > error TS1192: 'export \*' does not re-export a default. 52 | 53 | ### Broken Code ❌ 54 | 55 | ```ts 56 | export * from './parseUrls'; 57 | export * from './runWhenReady'; 58 | ``` 59 | 60 | You have to re-export a default (in this case coming from `runWhenReady.ts`): 61 | 62 | ### Fixed Code ✔️ 63 | 64 | ```ts 65 | export * from './parseUrls'; 66 | export * from './runWhenReady'; 67 | export {default as default} from './runWhenReady'; 68 | ``` 69 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1196.md: -------------------------------------------------------------------------------- 1 | ## TS1196 2 | 3 | > error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type MyError = { 9 | code: number; 10 | }; 11 | 12 | try { 13 | // ... 14 | } catch (error: MyError) { 15 | console.log(error.code); 16 | } 17 | ``` 18 | 19 | ### Fixed Code ✔️ 20 | 21 | Errors in catch clauses can only be typed with `any` or `unknown`. If you need a more precise error typing, you can use a **type guard** as follows: 22 | 23 | ```ts 24 | // Type Guard 25 | function isMyError(error: any): error is MyError { 26 | return typeof error.code === 'number'; 27 | } 28 | 29 | type MyError = { 30 | code: number; 31 | }; 32 | 33 | try { 34 | // ... 35 | } catch (error: unknown) { 36 | if (isMyError(error)) { 37 | console.log(error.code); 38 | } 39 | } 40 | ``` 41 | 42 | ### Video Tutorial 43 | 44 | {% youtube 0GLYiJUBz6k?start=72 'video' false %} 45 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1202.md: -------------------------------------------------------------------------------- 1 | ## TS1202 2 | 3 | > error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import \* as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import sinon = require('sinon'); 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | ```ts 14 | import * as sinon from 'sinon'; 15 | ``` 16 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1208.md: -------------------------------------------------------------------------------- 1 | ## TS1208 2 | 3 | > error TS1208: 'index.ts' cannot be compiled under '--isolatedModules' because it is considered a global script file. Add an import, export, or an empty 'export {}' statement to make it a module. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:json tsconfig.json %} 9 | { 10 | "compilerOptions": { 11 | "isolatedModules": true 12 | } 13 | } 14 | {% endcodeblock %} 15 | 16 | 17 | 18 | {% codeblock lang:ts index.ts %} 19 | require(`dotenv-defaults`).config({ 20 | path: '.env', 21 | }); 22 | {% endcodeblock %} 23 | 24 | 25 | ### Fixed Code ✔️ 26 | 27 | To solve the issue you can turn off "isolatedModules" in your "tsconfig.json". If you want to keep going with isolated modules, then you have to add an import or export to your code: 28 | 29 | 30 | {% codeblock lang:ts index.ts %} 31 | require(`dotenv-defaults`).config({ 32 | path: '.env', 33 | }); 34 | 35 | export default {}; 36 | {% endcodeblock %} 37 | 38 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1218.md: -------------------------------------------------------------------------------- 1 | ## TS1218 2 | 3 | > error TS1218: Export assignment is not supported when '--module' flag is 'system'. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts %} 9 | class LRUCache { 10 | // ... 11 | } 12 | 13 | export = LRUCache; 14 | {% endcodeblock %} 15 | 16 | 17 | ### Fixed Code ✔️ 18 | 19 | 20 | {% codeblock lang:ts mark:1,3 %} 21 | export class LRUCache { 22 | // ... 23 | } 24 | {% endcodeblock %} 25 | 26 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1219.md: -------------------------------------------------------------------------------- 1 | ## TS1219 2 | 3 | > error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import {Injectable} from '@nestjs/common'; 9 | 10 | @Injectable() 11 | export class AppService { 12 | getHello(): string { 13 | return 'Hello World!'; 14 | } 15 | } 16 | ``` 17 | 18 | ### Fixed Code ✔️ 19 | 20 | Simply set "experimentalDecorators" to `true` in your "tsconfig.json" file. As long as decorators are experimental you will also have to install the [reflect-metadata](https://github.com/rbuckton/reflect-metadata) package to shim the upcoming Metadata Reflection API for ECMAScript. For proper functionality the "emitDecoratorMetadata" option should also be set to `true`. 21 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1225.md: -------------------------------------------------------------------------------- 1 | ## TS1225 2 | 3 | > error TS1225: Cannot find parameter '`error`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const isError = (): input is Error => { 9 | return input instanceof Error; 10 | }; 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | A **type predicate** needs a parameter to validate: 16 | 17 | ```ts 18 | const isError = (input: unknown): input is Error => { 19 | return input instanceof Error; 20 | }; 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1228.md: -------------------------------------------------------------------------------- 1 | ## TS1228 2 | 3 | > error TS1228: A type predicate is only allowed in return type position for functions and methods. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function hasErrorCode(error: any) error is {code: string} { 9 | return typeof (error && error.code) === 'string' 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | You have to separate the argument list from the return type definition by a `:`: 16 | 17 | ```ts 18 | function hasErrorCode(error: any): error is {code: string} { 19 | return typeof (error && error.code) === 'string'; 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1243.md: -------------------------------------------------------------------------------- 1 | ## TS1243 2 | 3 | > error TS1243: 'static' modifier cannot be used with 'abstract' modifier. 4 | 5 | ### Solution 6 | 7 | ### Broken Code ❌ 8 | 9 | 10 | ```ts 11 | abstract class CustomNumber { 12 | abstract static getNumber(): number; 13 | } 14 | ``` 15 | 16 | 17 | Your `abstract class` cannot define an `abstract static` function. You have to keep it `static`: 18 | 19 | ### Fixed Code ✔️ 20 | 21 | 22 | ```ts 23 | abstract class CustomNumber { 24 | static getNumber(): number { 25 | return 1337; 26 | }; 27 | } 28 | ``` 29 | 30 | 31 | > error TS1243: 'async' modifier cannot be used with 'abstract' modifier. 32 | 33 | ### Broken Code ❌ 34 | 35 | 36 | ```ts 37 | abstract async goto(): Promise; 38 | ``` 39 | 40 | 41 | ### Fixed Code ✔️ 42 | 43 | 44 | ```ts 45 | abstract goto(): Promise; 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1244.md: -------------------------------------------------------------------------------- 1 | ## TS1244 2 | 3 | > error TS1244: Abstract methods can only appear within an abstract class. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | class Animal { 9 | abstract makeNoise(): string; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | ```ts 16 | abstract class Animal { 17 | abstract makeNoise(): string; 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1254.md: -------------------------------------------------------------------------------- 1 | ## TS1254 2 | 3 | > error TS1254: A 'const' initializer in an ambient context must be a string or numeric literal or literal enum reference. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock index.d.ts lang:ts %} 9 | declare module megalibrary { 10 | const MEGA_NUMBER = {}; 11 | } 12 | {% endcodeblock %} 13 | 14 | 15 | ### Fixed Code ✔️ 16 | 17 | 18 | {% codeblock index.d.ts lang:ts %} 19 | declare module megalibrary { 20 | const MEGA_NUMBER = 1337; 21 | } 22 | {% endcodeblock %} 23 | 24 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1259.md: -------------------------------------------------------------------------------- 1 | ## TS1259 2 | 3 | > error TS1259: Module can only be default-imported using the 'esModuleInterop' flag 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts main.ts %} 9 | import api from 'api'; 10 | {% endcodeblock %} 11 | 12 | 13 | 14 | {% codeblock lang:json tsconfig.json %} 15 | { 16 | "compilerOptions": { 17 | "lib": [ 18 | "dom", 19 | "es6" 20 | ], 21 | "module": "commonjs", 22 | "moduleResolution": "node", 23 | "outDir": "dist", 24 | "rootDir": "src", 25 | "target": "es6" 26 | } 27 | } 28 | {% endcodeblock %} 29 | 30 | 31 | ### Fixed Code ✔️ 32 | 33 | 34 | {% codeblock lang:json mark:3 tsconfig.json %} 35 | { 36 | "compilerOptions": { 37 | "esModuleInterop": true, 38 | "lib": [ 39 | "dom", 40 | "es6" 41 | ], 42 | "module": "commonjs", 43 | "moduleResolution": "node", 44 | "outDir": "dist", 45 | "rootDir": "src", 46 | "target": "es6" 47 | } 48 | } 49 | {% endcodeblock %} 50 | 51 | 52 | **Note:** You can enable the 'esModuleInterop' flag also via the CLI: 53 | 54 | ```bash 55 | tsc main.ts --esModuleInterop 56 | ``` 57 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1308.md: -------------------------------------------------------------------------------- 1 | ## TS1308 2 | 3 | > error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules.ts. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | React.useEffect(() => { 9 | const myPromise = Promise.resolve; 10 | await myPromise(); 11 | console.log('Promise is resolved.'); 12 | }, []); 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | You cannot use an `await` expression in an `useEffect` hook, but you can use legacy Promise calls: 18 | 19 | ```ts 20 | React.useEffect(() => { 21 | const myPromise = Promise.resolve; 22 | myPromise().then(() => { 23 | console.log('Promise is resolved.'); 24 | }); 25 | }, []); 26 | ``` 27 | 28 | Alternatively, you can use an **IIFE** (Immediately-invoked Function Expression) in your `useEffect` hook: 29 | 30 | ```ts 31 | React.useEffect(() => { 32 | (async () => { 33 | await Promise.resolve(); 34 | })(); 35 | }, []); 36 | ``` 37 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1337.md: -------------------------------------------------------------------------------- 1 | ## TS1337 2 | 3 | > error TS1337: An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export interface StreetMap { 9 | [city: 'New York']: ['Broadway', 'Park Avenue']; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | ```ts 16 | export type StreetMap = { 17 | 'New York': ['Broadway', 'Park Avenue']; 18 | }; 19 | ``` 20 | 21 | Alternative: 22 | 23 | ```ts 24 | export interface StreetMap { 25 | [city: string]: ['Broadway', 'Park Avenue']; 26 | } 27 | ``` 28 | 29 | > error TS1337: An index signature parameter type cannot be a union type. Consider using a mapped object type instead. 30 | 31 | ### Broken Code ❌ 32 | 33 | ```ts 34 | interface CustomError { 35 | [key: string | number]: string | number; 36 | } 37 | 38 | const error: CustomError = { 39 | 401: 'Unauthorized', 40 | }; 41 | ``` 42 | 43 | ### Fixed Code ✔️ 44 | 45 | Solution with **mapped object type**: 46 | 47 | ```ts 48 | type CustomError = { 49 | [key in number | string]: string | number; 50 | }; 51 | 52 | const error: CustomError = { 53 | 401: 'Unauthorized', 54 | }; 55 | ``` 56 | 57 | Alternative: 58 | 59 | ```ts 60 | interface ErrorNumber { 61 | [key: number]: string | number; 62 | } 63 | 64 | interface ErrorString { 65 | [key: string]: string | number; 66 | } 67 | 68 | const error: ErrorNumber | ErrorString = { 69 | 401: 'Unauthorized', 70 | }; 71 | ``` 72 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1341.md: -------------------------------------------------------------------------------- 1 | ## TS1341 2 | 3 | > error TS1341: Class constructor may not be an accessor. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | class SomeClass { 9 | get constructor() { 10 | // ... 11 | } 12 | set constructor(value) { 13 | // ... 14 | } 15 | } 16 | ``` 17 | 18 | ### Fixed Code ✔️ 19 | 20 | You can't name accessors as `constructor`: 21 | 22 | 23 | {% codeblock lang:ts mark:2,5 %} 24 | class SomeClass { 25 | get builder() { 26 | // ... 27 | } 28 | set builder(value) { 29 | // ... 30 | } 31 | } 32 | {% endcodeblock %} 33 | 34 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1355.md: -------------------------------------------------------------------------------- 1 | ## TS1355 2 | 3 | > error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const result = (Math.random() < 0.5 ? 0 : 1) as const; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | You cannot apply a const assertion to the result of a ternary operator. It is necessary to restrict the usage of const assertions to the individual literal expressions: 14 | 15 | ```ts 16 | const result = Math.random() < 0.5 ? (0 as const) : (1 as const); 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1357.md: -------------------------------------------------------------------------------- 1 | ## TS1357 2 | 3 | > error TS1357: An enum member name must be followed by a '`,`', '`=`', or '`}`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | enum GameAction { 9 | RUN : 'RUN' 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | ```ts 16 | enum GameAction { 17 | RUN = 'RUN', 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1361.md: -------------------------------------------------------------------------------- 1 | ## TS1361 2 | 3 | > error TS1361: '`Range`' cannot be used as a value because it was imported using 'import type'. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts %} 9 | import type { Range, TextEditor } from "vscode"; 10 | 11 | export class Ranger { 12 | static getFullRange(editor: TextEditor): Range { 13 | const lastLine = textEditor.document.lineAt(textEditor.document.lineCount - 1); 14 | const firstLine = textEditor.document.lineAt(0); 15 | return new Range(firstLine.range.start, lastLine.range.end); 16 | } 17 | } 18 | {% endcodeblock %} 19 | 20 | 21 | ### Fixed Code ✔️ 22 | 23 | The type `Range` is being used to declare the return type of static function `Ranger.getFullRange` but later on it is also being used to create an instance using `new Range`. When you want to use a type to construct instances (or do anything else beyond declaring types), then you have to use the `import` statement instead of `import type`: 24 | 25 | 26 | {% codeblock lang:ts mark:2 %} 27 | import type { TextEditor } from 'vscode'; 28 | import { Range } from 'vscode'; 29 | 30 | export class Ranger { 31 | static getFullRange(editor: TextEditor): Range { 32 | const lastLine = textEditor.document.lineAt(textEditor.document.lineCount - 1); 33 | const firstLine = textEditor.document.lineAt(0); 34 | return new Range(firstLine.range.start, lastLine.range.end); 35 | } 36 | } 37 | {% endcodeblock %} 38 | 39 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1363.md: -------------------------------------------------------------------------------- 1 | ## TS1363 2 | 3 | > error TS1363: A type-only import can specify a default import or named bindings, but not both. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import type MyDog, {MyPerson} from './MyPerson'; 9 | 10 | export function printAge(personOrDog: MyPerson | MyDog) { 11 | console.log(personOrDog.age); 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | With [type-only imports and exports](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export) you cannot use a **default import** together with a **named import** in one single line of code. The TypeScript team chose this limitation to avoid ambiguity. You will have to use separate import statements: 18 | 19 | ```ts 20 | import type {MyPerson} from './MyPerson'; 21 | import type MyDog from './MyPerson'; 22 | 23 | export function printAge(personOrDog: MyPerson | MyDog) { 24 | console.log(personOrDog.age); 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1368.md: -------------------------------------------------------------------------------- 1 | ## TS1368 2 | 3 | > error TS1368: Class constructor may not be a generator. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | class SomeClass { 9 | *constructor() { 10 | // ... 11 | } 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | You can't name generators as `constructor`: 18 | 19 | 20 | {% codeblock lang:ts mark:2 %} 21 | class SomeClass { 22 | *builder() { 23 | // ... 24 | } 25 | } 26 | {% endcodeblock %} 27 | 28 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1371.md: -------------------------------------------------------------------------------- 1 | ## TS1371 2 | 3 | > error TS1371: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts MyPerson.ts %} 9 | export class MyPerson { 10 | constructor(public name: string, public age: number) { 11 | } 12 | } 13 | {% endcodeblock %} 14 | 15 | 16 | 17 | {% codeblock lang:ts printAge.ts %} 18 | import {MyPerson} from './MyPerson'; 19 | 20 | export function printAge(person: MyPerson) { 21 | console.log(person.age); 22 | } 23 | {% endcodeblock %} 24 | 25 | 26 | ### Fixed Code ✔️ 27 | 28 | **Solution 1:** 29 | 30 | When "importsNotUsedAsValues" is set to "error" in your "tsconfig.json", then you have to use the "import type" syntax when you just want to refer to a type instead of using it as a value: 31 | 32 | 33 | {% codeblock lang:ts printAge.ts mark:1 %} 34 | import type {MyPerson} from './MyPerson'; 35 | 36 | export function printAge(person: MyPerson) { 37 | console.log(person.age); 38 | } 39 | {% endcodeblock %} 40 | 41 | 42 | **Solution 2:** 43 | 44 | Use the class also as a value and not just a type: 45 | 46 | 47 | {% codeblock lang:ts printAge.ts mark:7 %} 48 | import {MyPerson} from './MyPerson'; 49 | 50 | export function printAge(person: MyPerson) { 51 | console.log(person.age); 52 | } 53 | 54 | const benny = new MyPerson('Benny', 35); 55 | printAge(benny); 56 | {% endcodeblock %} 57 | 58 | 59 | **Solution 3:** 60 | 61 | You can also set "importsNotUsedAsValues" to "preserve" which is not recommended. 62 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1375.md: -------------------------------------------------------------------------------- 1 | ## TS1375 2 | 3 | > error TS1375: 'await' expressions are only allowed at the top level of a file when that file is a module, but this file has no imports or exports. Consider adding an empty 'export {}' to make this file a module. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const response = await fetch('https://jsonplaceholder.typicode.com/todos/1'); 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | ```ts 14 | export {}; 15 | 16 | const response = await fetch('https://jsonplaceholder.typicode.com/todos/1'); 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1378.md: -------------------------------------------------------------------------------- 1 | ## TS1378 2 | 3 | > error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:json tsconfig.json %} 9 | { 10 | "compilerOptions": { 11 | "lib": ["es2017"], 12 | "module": "commonjs", 13 | "outDir": "dist", 14 | "rootDir": "src", 15 | "target": "es6" 16 | } 17 | } 18 | {% endcodeblock %} 19 | 20 | 21 | ### Fixed Code ✔️ 22 | 23 | 24 | {% codeblock lang:json tsconfig.json mark:4,7 %} 25 | { 26 | "compilerOptions": { 27 | "lib": ["es2017"], 28 | "module": "esnext", 29 | "outDir": "dist", 30 | "rootDir": "src", 31 | "target": "es2017" 32 | } 33 | } 34 | {% endcodeblock %} 35 | 36 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1385.md: -------------------------------------------------------------------------------- 1 | ## TS1385 2 | 3 | > error TS1385: Function type notation must be parenthesized when used in a union type. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type MyCallback = () => number | () => string 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | When using a [**union type**](/glossary/index.html#Union-Types), you have to put additional function types in parentheses: 14 | 15 | ```ts 16 | type MyCallback = () => number | (() => string); 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1389.md: -------------------------------------------------------------------------------- 1 | ## TS1389 2 | 3 | > error TS1389: 'this' is not allowed as a variable declaration name. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const this = 'something'; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | The name `this` cannot be used to declare a variable because it is already a reserved keyword to refer to the current object in a method or constructor. 14 | 15 | That's why you have to choose a different name: 16 | 17 | ```ts 18 | const that = 'something'; 19 | ``` 20 | 21 | {% youtube -gUV7jhdalA 'video' false %} 22 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1431.md: -------------------------------------------------------------------------------- 1 | ## TS1431 2 | 3 | > error TS1431: 'for await' loops are only allowed at the top level of a file when that file is a module, but this file has no imports or exports. Consider adding an empty 'export {}' to make this file a module. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const inputStream = fs.createReadStream('file.csv'); 9 | 10 | const rl = readline.createInterface({ 11 | input: inputStream, 12 | crlfDelay: Infinity, 13 | }); 14 | 15 | for await (const line of rl) { 16 | console.log(line); 17 | } 18 | ``` 19 | 20 | ### Fixed Code ✔️ 21 | 22 | Just add the imports for the `fs` module and `readline` module in order to turn your code into a module itself: 23 | 24 | ```ts 25 | import fs from 'node:fs'; 26 | import readline from 'node:readline'; 27 | 28 | const inputStream = fs.createReadStream('file.csv'); 29 | 30 | const rl = readline.createInterface({ 31 | input: inputStream, 32 | crlfDelay: Infinity, 33 | }); 34 | 35 | for await (const line of rl) { 36 | console.log(line); 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1432.md: -------------------------------------------------------------------------------- 1 | ## TS1432 2 | 3 | > error TS1432: Top-level 'for await' loops are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', or 'nodenext', and the 'target' option is set to 'es2017' or higher. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts start.ts %} 9 | import fs from 'node:fs'; 10 | import readline from 'node:readline'; 11 | 12 | const file = 'abc.csv'; 13 | 14 | const fileStream = fs.createReadStream(file); 15 | 16 | const rl = readline.createInterface({ 17 | input: fileStream, 18 | crlfDelay: Infinity 19 | }); 20 | 21 | for await (const line of rl) { 22 | console.log(`Line from file: ${line}`); 23 | } 24 | {% endcodeblock %} 25 | 26 | 27 | 28 | {% codeblock lang:json tsconfig.json %} 29 | { 30 | "compilerOptions": { 31 | "lib": ["es2017"], 32 | "module": "commonjs", 33 | "target": "es6" 34 | } 35 | } 36 | {% endcodeblock %} 37 | 38 | 39 | ### Fixed Code ✔️ 40 | 41 | The error is similar to **TS1378** and needs an adjustment in the `tsconfig.json` file: 42 | 43 | 44 | {% codeblock lang:json tsconfig.json mark:4,5 %} 45 | { 46 | "compilerOptions": { 47 | "lib": ["es2017"], 48 | "module": "esnext", 49 | "target": "es2017" 50 | } 51 | } 52 | {% endcodeblock %} 53 | 54 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1434.md: -------------------------------------------------------------------------------- 1 | ## TS1434 2 | 3 | > error TS1434: Unexpected keyword or identifier. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | class MyClass { 9 | static static ID: number = 1337; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | You have to remove the duplicate `static` keyword: 16 | 17 | ```ts 18 | class MyClass { 19 | static ID: number = 1337; 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS1xxx/TS1471.md: -------------------------------------------------------------------------------- 1 | ## TS1471 2 | 3 | > TS1471: Module '`@headlessui/react`' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import {FocusTrap} from '@headlessui/react'; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | Using a **dynamic import**: 14 | 15 | ```ts 16 | const {FocusTrap} = await import('@headlessui/react'); 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2300.md: -------------------------------------------------------------------------------- 1 | ## TS2300 2 | 3 | > error TS2300: Duplicate identifier 'name'. 4 | 5 | ### Broken Code ❌ 6 | 7 | Objects don't support multiple properties with the same name: 8 | 9 | ```ts 10 | const objectLiteral = { 11 | name: 'Benny', 12 | name: 'Sofia', 13 | }; 14 | ``` 15 | 16 | ### Fixed Code ✔️ 17 | 18 | To fix the error we have to remove the duplicated property: 19 | 20 | ```ts 21 | const objectLiteral = { 22 | name: 'Sofia', 23 | }; 24 | ``` 25 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2304.md: -------------------------------------------------------------------------------- 1 | ## TS2304 2 | 3 | > error TS2304: Cannot find name 'world'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | console.log(world.name); 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | It can happen that TypeScript does not know about your global objects because those may be injected from an unknown runtime environment or third-party JavaScript library. The easiest way to let TypeScript know about this is to declare the ambience ([ambient context](/glossary/index.html#Ambient-Context)): 14 | 15 | ```ts 16 | declare var world: { 17 | name: string; 18 | }; 19 | 20 | console.log(world.name); 21 | ``` 22 | 23 | > error TS2304: Cannot find name 'Promise' 24 | 25 | ### Broken Code ❌ 26 | 27 | ```ts 28 | // ... 29 | 30 | public load_prekey(prekey_id: number): Promise { 31 | return new Promise((resolve) => { 32 | resolve(42); 33 | }); 34 | } 35 | 36 | // ... 37 | ``` 38 | 39 | ### Fixed Code ✔️ 40 | 41 | Install `es6-promise` type definitions with the [typings](https://github.com/typings/typings) tool. 42 | 43 | ```bash 44 | typings install dt~es6-promise --global --save 45 | ``` 46 | 47 | Adding the following line to the beginning of every file using definitions from `es6-promise`. 48 | 49 | ```ts 50 | /// 51 | 52 | ... 53 | 54 | public load_prekey(prekey_id: number): Promise { 55 | return new Promise((resolve) => { 56 | resolve(42); 57 | }); 58 | } 59 | 60 | ... 61 | ``` 62 | 63 | > error TS2304: Cannot find name 'Promise' 64 | 65 | ### Broken Code ❌ 66 | 67 | ```ts 68 | const UUID = require('uuidjs'); 69 | ``` 70 | 71 | ### Fixed Code ✔️ 72 | 73 | ```bash 74 | npm install @types/node --save-dev 75 | ``` 76 | 77 | > error TS2304: Cannot find name 'FC'. 78 | 79 | ### Broken Code ❌ 80 | 81 | ```tsx 82 | import React from 'react'; 83 | 84 | const App: FC = (): JSX.Element => { 85 | return <>; 86 | }; 87 | ``` 88 | 89 | ### Fixed Code ✔️ 90 | 91 | ```tsx 92 | import React, {FC} from 'react'; 93 | 94 | const App: FC = (): JSX.Element => { 95 | return <>; 96 | }; 97 | ``` 98 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2305.md: -------------------------------------------------------------------------------- 1 | ## TS2305 2 | 3 | > error TS2305: Module '`./sum`' has no exported member '`multiply`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts sum.ts %} 9 | export function sum(a: number, b: number): number { 10 | return a + b; 11 | } 12 | {% endcodeblock %} 13 | 14 | 15 | 16 | {% codeblock lang:ts main.ts %} 17 | import { multiply } from './sum'; 18 | 19 | console.log(multiply(1, 2)); 20 | {% endcodeblock %} 21 | 22 | 23 | ### Fixed Code ✔️ 24 | 25 | The file "sum.ts" exports a function named "sum", so we have to fix the **named import** in our "main.ts" file: 26 | 27 | 28 | {% codeblock lang:ts main.ts %} 29 | import { sum } from './sum'; 30 | 31 | console.log(sum(1, 2)); 32 | {% endcodeblock %} 33 | 34 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2306.md: -------------------------------------------------------------------------------- 1 | ## TS2306 2 | 3 | > error TS2306: File '`add.ts`' is not a module. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock add.ts lang:ts %} 9 | function add(a: number, b: number): number { 10 | return a + b; 11 | } 12 | {% endcodeblock %} 13 | 14 | 15 | 16 | {% codeblock main.ts lang:ts %} 17 | import { add } from './add'; 18 | 19 | console.log(add(1000, 337)); 20 | {% endcodeblock %} 21 | 22 | 23 | ### Fixed Code ✔️ 24 | 25 | The error TS2306 signals that the file (`add.ts`) can be found (otherwise it would throw [error TS2307](#TS2307)) but does not provide the necessary exports. We can solve this with a named export: 26 | 27 | 28 | {% codeblock add.ts lang:ts %} 29 | export function add(a: number, b: number): number { 30 | return a + b; 31 | } 32 | {% endcodeblock %} 33 | 34 | 35 | Alternatively we can use a default export: 36 | 37 | 38 | {% codeblock add.ts lang:ts %} 39 | export default function add(a: number, b: number): number { 40 | return a + b; 41 | } 42 | {% endcodeblock %} 43 | 44 | 45 | Using a default export requires that we also adjust our import statement in `main.ts` (otherwise we would end up with [error TS2614](#TS2614)): 46 | 47 | 48 | {% codeblock main.ts lang:ts %} 49 | import add from './add'; 50 | 51 | console.log(add(1000, 337)); 52 | {% endcodeblock %} 53 | 54 | 55 | ### Video Tutorial 56 | 57 | {% youtube XoOgNRQEYws?start=675 'video' false %} 58 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2307.md: -------------------------------------------------------------------------------- 1 | ## TS2307 2 | 3 | > error TS2307: Cannot find module 'events' or its corresponding type declarations. 4 | 5 | ### Broken Code ❌ 6 | 7 | You are importing from a core Node.js module (e.g. `event`) without having Node.js type definitions installed: 8 | 9 | ```ts 10 | import {EventEmitter} from 'events'; 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | Import Node.js type definitions first in order to use Node.js core modules: 16 | 17 | ```bash 18 | npm install @types/node 19 | ``` 20 | 21 | More: {% post_link error-ts2307-cannot-find-module-events %} 22 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2314.md: -------------------------------------------------------------------------------- 1 | ## TS2314 2 | 3 | > error TS2314: Generic type '`Omit`' requires 2 type argument(s). 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export interface SerializedBatchedCandle extends Omit { 9 | open: string; 10 | close: string; 11 | } 12 | ``` 13 | 14 | ### Fixed Code ✔️ 15 | 16 | When using the `Omit` utility type, you have to list property overwrites with a pipe (`|`): 17 | 18 | ```ts 19 | export interface SerializedBatchedCandle extends Omit { 20 | close: string; 21 | closeAsk: string; 22 | } 23 | ``` 24 | 25 | > TS2314: Generic type '`ReadonlyArray` ' requires 1 type argument(s). 26 | 27 | ### Broken Code ❌ 28 | 29 | ```ts 30 | const array: ReadonlyArray = [1, 2, 3] as const; 31 | ``` 32 | 33 | ### Fixed Code ✔️ 34 | 35 | When using a generic (in this case `ReadonlyArray`), then you have to pass a **type argument** to it: 36 | 37 | ```ts 38 | const array: ReadonlyArray = [1, 2, 3] as const; 39 | ``` 40 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2315.md: -------------------------------------------------------------------------------- 1 | ## TS2315 2 | 3 | > error TS2315: Type '`CustomRequest`' is not generic. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type CustomRequest = { 9 | url: string; 10 | data: string; 11 | }; 12 | 13 | const request: CustomRequest = { 14 | url: 'https://typescript.tv/', 15 | data: 'example', 16 | }; 17 | ``` 18 | 19 | ### Fixed Code ✔️ 20 | 21 | When supplying a type (recognizable by the use of the **diamond operator** `<>`), then we have to make sure that our type actually supports **generics** to capture the type that we provide: 22 | 23 | ```ts 24 | type CustomRequest = { 25 | url: string; 26 | data: CustomType; 27 | }; 28 | 29 | const request: CustomRequest = { 30 | url: 'https://typescript.tv/', 31 | data: 'example', 32 | }; 33 | ``` 34 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2322.md: -------------------------------------------------------------------------------- 1 | ## TS2322 2 | 3 | > error TS2322: Type 'string' is not assignable to type 'number'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export function add(a: number, b: number): number { 9 | return `${a + b}`; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | The type of the returned value must match the return type specified in the function signature: 16 | 17 | ```ts 18 | export function add(a: number, b: number): number { 19 | return parseInt(`${a + b}`, 10); 20 | } 21 | ``` 22 | 23 | ### Video Tutorial 24 | 25 | {% youtube 8N_P-l5Kukk?start=398 'video' false %} 26 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2335.md: -------------------------------------------------------------------------------- 1 | ## TS2335 2 | 3 | > error TS2335: 'super' can only be referenced in a derived class. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | abstract class Animal { 9 | abstract makeNoise(): string; 10 | } 11 | 12 | class Cat { 13 | constructor() { 14 | super(); 15 | } 16 | 17 | makeNoise(): string { 18 | return 'Meow!'; 19 | } 20 | } 21 | ``` 22 | 23 | ### Fixed Code ✔️ 24 | 25 | Your derived class has to "extend" the base class: 26 | 27 | ```ts 28 | abstract class Animal { 29 | abstract makeNoise(): string; 30 | } 31 | 32 | class Cat extends Animal { 33 | constructor() { 34 | super(); 35 | } 36 | 37 | makeNoise(): string { 38 | return 'Meow!'; 39 | } 40 | } 41 | ``` 42 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2344.md: -------------------------------------------------------------------------------- 1 | ## TS2344 2 | 3 | > error TS2344: Type '`{ name: string; }`' does not satisfy the constraint '`{ age: number; }`'. Property '`age`' is missing in type '`{ name: string; }`' but required in type '`{ age: number; }`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts mark:6 %} 9 | function increaseAge(data: T): T { 10 | data.age += 1; 11 | return data; 12 | } 13 | 14 | increaseAge<{ name: string }>({age: 25, name: 'Benny'}); 15 | {% endcodeblock %} 16 | 17 | 18 | ### Fixed Code ✔️ 19 | 20 | When passing a **type argument**, the required properties of the **type variable** (`T`) must be matched: 21 | 22 | 23 | {% codeblock lang:ts mark:6 %} 24 | function increaseAge(data: T): T { 25 | data.age += 1; 26 | return data; 27 | } 28 | 29 | increaseAge<{ age: number, name: string }>({age: 25, name: 'Benny'}); 30 | {% endcodeblock %} 31 | 32 | 33 | As an alternative, **type argument inference** can be used: 34 | 35 | 36 | {% codeblock lang:ts mark:6 %} 37 | function increaseAge(data: T): T { 38 | data.age += 1; 39 | return data; 40 | } 41 | 42 | increaseAge({age: 25, name: 'Benny'}); 43 | {% endcodeblock %} 44 | 45 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2345.md: -------------------------------------------------------------------------------- 1 | ## TS2345 2 | 3 | > error TS2345: Argument of type '`number`' is not assignable to parameter of type '`TimerHandler`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function add(a: number, b: number): number { 9 | return a + b; 10 | } 11 | 12 | setTimeout(add(1000, 337), 5000); 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | There is a mismatch in the expected arguments of a function. The `setTimeout` function expects the first argument to be a callback function and not the returned value (in this case a `number`) of a function call: 18 | 19 | 20 | {% codeblock lang:ts mark:5 %} 21 | function add(a: number, b: number): number { 22 | return a + b; 23 | } 24 | 25 | setTimeout(() => add(1000, 337), 5000); 26 | {% endcodeblock %} 27 | 28 | 29 | ### Video Tutorial 30 | 31 | {% youtube xLa0wmolvV8?start=145 'video' false %} 32 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2348.md: -------------------------------------------------------------------------------- 1 | ## TS2348 2 | 3 | > error TS2348: Value of type 'typeof BaseN' is not callable. Did you mean to include 'new'? 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import {BaseN} from 'js-combinatorics'; 9 | 10 | const iterator = BaseN([1, 2, 3], 2); 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | ```ts 16 | import {BaseN} from 'js-combinatorics'; 17 | 18 | const iterator = new BaseN([1, 2, 3], 2); 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2349.md: -------------------------------------------------------------------------------- 1 | ## TS2349 2 | 3 | > error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'Promise' has no compatible call signatures. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts %} 9 | function bugged(param: Promise): void { 10 | param().then(() => console.log('error TS2349')); 11 | } 12 | {% endcodeblock %} 13 | 14 | 15 | ### Fixed Code ✔️ 16 | 17 | 18 | {% codeblock lang:ts mark:2 %} 19 | function bugged(param: Promise): void { 20 | param.then(() => console.log('error TS2349')); 21 | } 22 | {% endcodeblock %} 23 | 24 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2351.md: -------------------------------------------------------------------------------- 1 | ## TS2351 2 | 3 | > error TS2351: This expression is not constructable. Type '`EMA`' has no construct signatures. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts RSI.ts %} 9 | export class RSI { 10 | private readonly avgGain: MovingAverage; 11 | 12 | constructor(private readonly interval: number, Indicator: EMA) { 13 | this.avgGain = new Indicator(this.interval); 14 | } 15 | } 16 | {% endcodeblock %} 17 | 18 | 19 | 20 | {% codeblock lang:ts EMA.ts %} 21 | export class EMA {} 22 | {% endcodeblock %} 23 | 24 | 25 | ### Fixed Code ✔️ 26 | 27 | 28 | {% codeblock lang:ts RSI.ts mark:4 %} 29 | export class RSI { 30 | private readonly avgGain: MovingAverage; 31 | 32 | constructor(private readonly interval: number, Indicator: typeof EMA) { 33 | this.avgGain = new Indicator(this.interval); 34 | } 35 | } 36 | {% endcodeblock %} 37 | 38 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2352.md: -------------------------------------------------------------------------------- 1 | ## TS2352 2 | 3 | > error TS2352: Conversion of type '`{ name: string; age: number; }`' to type '`Person`' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to '`unknown`' first. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type Person = { 9 | firstName: string; 10 | age: number; 11 | }; 12 | 13 | const myObject = { 14 | name: 'Benny', 15 | age: 34, 16 | } as Person; 17 | ``` 18 | 19 | ### Fixed Code ✔️ 20 | 21 | Make sure all properties of your object match the properties of your declared type: 22 | 23 | ```ts 24 | type Person = { 25 | firstName: string; 26 | age: number; 27 | }; 28 | 29 | const myObject = { 30 | firstName: 'Benny', 31 | age: 34, 32 | } as Person; 33 | ``` 34 | 35 | Alternative but not recommended: Convert your object to `unknown` first: 36 | 37 | ```ts 38 | type Person = { 39 | firstName: string; 40 | age: number; 41 | }; 42 | 43 | const myObject = { 44 | name: 'Benny', 45 | age: 34, 46 | } as unknown as Person; 47 | ``` 48 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2355.md: -------------------------------------------------------------------------------- 1 | ## TS2355 2 | 3 | > error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | getName(): string { 9 | 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | ```ts 16 | getName(): string { 17 | return 'Benny'; 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2361.md: -------------------------------------------------------------------------------- 1 | ## TS2361 2 | 3 | > error TS2361: The right-hand side of an 'in' expression must not be a primitive. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import axios, {AxiosError} from 'axios'; 9 | 10 | const isAxiosError = (error: unknown): error is AxiosError => { 11 | return 'isAxiosError' in error; 12 | }; 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | You cannot use the `in` keyword on primitive data types. That's why we have to replace the primitive type `unknown` with a non-primitive type like `object`: 18 | 19 | ```ts 20 | import axios, {AxiosError} from 'axios'; 21 | 22 | const isAxiosError = (error: object): error is AxiosError => { 23 | return 'isAxiosError' in error; 24 | }; 25 | ``` 26 | 27 | An alternative solution would be to use a **type assertion** on the right-hand side of the 'in' expression: 28 | 29 | ```ts 30 | const isAxiosError = (error: unknown): error is AxiosError => { 31 | return 'isAxiosError' in (error as AxiosError); 32 | }; 33 | ``` 34 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2362.md: -------------------------------------------------------------------------------- 1 | ## TS2362 2 | 3 | > error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const userName = {name: 'Benny'}; 9 | const userAge = {age: 35}; 10 | const user = userName & userAge; 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | When you want to merge two objects, you have a multitude of possibilities: 16 | 17 | **Spread Syntax** 18 | 19 | ```ts 20 | const userName = {name: 'Benny'}; 21 | const userAge = {age: 35}; 22 | const user = { 23 | ...userName, 24 | ...userAge, 25 | }; 26 | ``` 27 | 28 | **Object.assign** 29 | 30 | ```ts 31 | const userName = {name: 'Benny'}; 32 | const userAge = {age: 35}; 33 | const user = Object.assign({}, userName, userAge); 34 | ``` 35 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2364.md: -------------------------------------------------------------------------------- 1 | ## TS2364 2 | 3 | > error TS2364: The left-hand side of an assignment expression must be a variable or a property access. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | 1 = 1; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | Using a variable on the left-hand side assignment: 14 | 15 | ```ts 16 | const a = 1; 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2365.md: -------------------------------------------------------------------------------- 1 | ## TS2365 2 | 3 | > error TS2365: Operator '+' cannot be applied to types 'number' and 'object'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export function add(a: number, b: object): number { 9 | return a + b; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | You can use the `+` operator only with equivalent data types (strings + strings or numbers + numbers): 16 | 17 | ```ts 18 | export function add(a: number, b: number): number { 19 | return a + b; 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2366.md: -------------------------------------------------------------------------------- 1 | ## TS2366 2 | 3 | > error TS2366: Function lacks ending return statement and return type does not include 'undefined'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export function getInterestRate(years: 1 | 2 | 3): number { 9 | switch (years) { 10 | case 1: 11 | return 1.75; 12 | case 2: 13 | return 2.96; 14 | } 15 | } 16 | ``` 17 | 18 | ### Fixed Code ✔️ 19 | 20 | The switch-case statement isn't handling all cases from every possible input. We can solve that by defining a `default` case: 21 | 22 | ```ts 23 | export function getInterestRate(years: 1 | 2 | 3): number { 24 | switch (years) { 25 | case 1: 26 | return 1.75; 27 | case 2: 28 | return 2.96; 29 | default: 30 | return 3; 31 | } 32 | } 33 | ``` 34 | 35 | Another solution would be to implement the missing case for `3`: 36 | 37 | ```ts 38 | export function getInterestRate(years: 1 | 2 | 3): number { 39 | switch (years) { 40 | case 1: 41 | return 1.75; 42 | case 2: 43 | return 2.96; 44 | case 3: 45 | return 3; 46 | } 47 | } 48 | ``` 49 | 50 | ### Video Tutorial 51 | 52 | {% youtube 8N_P-l5Kukk?start=107 'video' false %} 53 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2367.md: -------------------------------------------------------------------------------- 1 | ## TS2367 2 | 3 | > error TS2367: This condition will always return 'false' since the types '{ message: string; }[] | undefined' and 'number' have no overlap. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function myTest(errors: {message: string}[]): void { 9 | if (errors === 0) { 10 | throw new Error(); 11 | } 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | An array cannot be `0`, so doing a check for equality with `0` makes no sense. What may be useful instead is checking the array length: 18 | 19 | ```ts 20 | function myTest(errors: {message: string}[]): void { 21 | if (errors.length === 0) { 22 | throw new Error(); 23 | } 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2368.md: -------------------------------------------------------------------------------- 1 | ## TS2368 2 | 3 | > error TS2368: Type parameter name cannot be 'number'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export interface SimpleNumberIndicator { 9 | update(price: T): T; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | The easiest way to fix the error is to make `age` optional as well: 16 | 17 | ```ts 18 | export interface SimpleNumberIndicator { 19 | update(price: T): T; 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2369.md: -------------------------------------------------------------------------------- 1 | ## TS2369 2 | 3 | > error TS2369: A parameter property is only allowed in a constructor implementation. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | class MyMessenger { 9 | constructor(public message: string); 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | The constructor implementation is missing **curly brackets** which is why TypeScript does not recognize the constructor implementation and files error **TS2369**. To solve it you have to add the missing curly brackets: 16 | 17 | ```ts 18 | class MyMessenger { 19 | constructor(public message: string) {} 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2370.md: -------------------------------------------------------------------------------- 1 | ## TS2370 2 | 3 | > error TS2370: A rest parameter must be of an array type. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function sum(...array: number): number { 9 | return array.reduce((a, b) => a + b); 10 | } 11 | 12 | console.log(sum(...[1, 2, 3, 4, 5])); 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | A rest parameter allows a function to accept an indefinite number of parameters. To signal that it can be multiple values, we have to use an `array` type for our rest parameter: 18 | 19 | ```ts 20 | function sum(...array: number[]): number { 21 | return array.reduce((a, b) => a + b); 22 | } 23 | 24 | console.log(sum(...[1, 2, 3, 4, 5])); 25 | ``` 26 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2371.md: -------------------------------------------------------------------------------- 1 | ## TS2371 2 | 3 | > error TS2371: A parameter initializer is only allowed in a function or constructor implementation. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function add(a: number, b: number, c: number = 0): number; 9 | function add(a: number | string, b: number | string, c: number | string = 0): number { 10 | return parseInt(`${a}`, 10) + parseInt(`${b}`, 10); 11 | } 12 | ``` 13 | 14 | ### Fixed Code ✔️ 15 | 16 | Remove parameter initializer from function overload: 17 | 18 | ```ts 19 | function add(a: number, b: number, c: number): number; 20 | function add(a: number | string, b: number | string, c: number | string = 0): number { 21 | return parseInt(`${a}`, 10) + parseInt(`${b}`, 10); 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2372.md: -------------------------------------------------------------------------------- 1 | ## TS2372 2 | 3 | > error TS2372: Parameter '`score`' cannot reference itself. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function printScore(score: number = score): void { 9 | console.log(score); 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | If you want to use a **default value** for a parameter, then you have to set it to a fixed value instead of referencing the parameter to itself: 16 | 17 | ```ts 18 | function printScore(score: number = 0): void { 19 | console.log(score); 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2377.md: -------------------------------------------------------------------------------- 1 | ## TS2377 2 | 3 | > error TS2377: Constructors for derived classes must contain a 'super' call. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | abstract class Animal { 9 | abstract name: string; 10 | } 11 | 12 | class Dog extends Animal { 13 | public name; 14 | 15 | constructor(name: string) { 16 | this.name = name; 17 | } 18 | } 19 | ``` 20 | 21 | ### Fixed Code ✔️ 22 | 23 | Every `constructor` in a derived class has to call the `super` method to invoke the `constructor` of the base class. It has to be the very first call: 24 | 25 | ```ts 26 | abstract class Animal { 27 | abstract name: string; 28 | } 29 | 30 | class Dog extends Animal { 31 | public name; 32 | 33 | constructor(name: string) { 34 | super(); 35 | this.name = name; 36 | } 37 | } 38 | ``` 39 | 40 | ### Video Tutorial 41 | 42 | {% youtube 62J_eQsK0e0?start=635 'video' false %} 43 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2378.md: -------------------------------------------------------------------------------- 1 | ## TS2378 2 | 3 | > error TS2378: A 'get' accessor must return a value. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | get name() { 9 | 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | ```ts 16 | get name(): string { 17 | return 'Benny'; 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2390.md: -------------------------------------------------------------------------------- 1 | ## TS2390 2 | 3 | > error TS2390: Constructor implementation is missing. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | class MyMessenger { 9 | constructor(public message: string); 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | A constructor implementation must be put in **curly brackets**: 16 | 17 | ```ts 18 | class MyMessenger { 19 | constructor(public message: string) {} 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2391.md: -------------------------------------------------------------------------------- 1 | ## TS2391 2 | 3 | > error TS2391: Function implementation is missing or not immediately following the declaration. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | abstract class Animal { 9 | abstract name: string; 10 | makeNoise(): string; 11 | } 12 | ``` 13 | 14 | ### Fixed Code ✔️ 15 | 16 | An abstract class is different from an interface. You have to use the `abstract` modifier if you want to define a contract in an abstract class. If there is no `abstract` modifier you will have to provide a implementation. 17 | 18 | Solution 1: 19 | 20 | To solve the problem, we can mark `makeNoise` with the `abstract` keyword. That will enforce derived classes to implement this method on their own: 21 | 22 | ```ts 23 | abstract class Animal { 24 | abstract name: string; 25 | abstract makeNoise(): string; 26 | } 27 | ``` 28 | 29 | Solution 2: 30 | 31 | Another solution is to provide a base implementation for `makeNoise`: 32 | 33 | ```ts 34 | abstract class Animal { 35 | abstract name: string; 36 | makeNoise(): string { 37 | return 'Woof'; 38 | } 39 | } 40 | ``` 41 | 42 | ### Video Tutorial 43 | 44 | {% youtube 62J_eQsK0e0?start=430 'video' false %} 45 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2394.md: -------------------------------------------------------------------------------- 1 | ## TS2394 2 | 3 | > error TS2394: This overload signature is not compatible with its implementation signature. 4 | 5 | ### Broken Code ❌ 6 | 7 | The implementation does not match all signatures: 8 | 9 | ```ts 10 | function sum(a: number, b: number): number; 11 | function sum(a: string, b: string): string; 12 | function sum(a: number | string, b: number | string) { 13 | return `${parseInt(a + '', 10) + parseInt(b + '', 10)}`; 14 | } 15 | ``` 16 | 17 | ### Fixed Code ✔️ 18 | 19 | To match the first function overload, we have to add code to our function body which can also return a `number`: 20 | 21 | 22 | {% codeblock lang:ts mark:4-6 %} 23 | function sum(a: number, b: number): number; 24 | function sum(a: string, b: string): string; 25 | function sum(a: number | string, b: number | string) { 26 | if (typeof a === 'number' && typeof b === 'number') { 27 | return a + b; 28 | } 29 | return `${parseInt(a + '', 10) + parseInt(b + '', 10)}`; 30 | } 31 | {% endcodeblock %} 32 | 33 | 34 | ### Video Tutorial 35 | 36 | {% youtube xLa0wmolvV8?start=217 'video' false %} 37 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2395.md: -------------------------------------------------------------------------------- 1 | ## TS2395 2 | 3 | > error TS2395: Individual declarations in merged declaration '`React`' must be all exported or all local. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts index.d.ts %} 9 | import * as React from 'react'; 10 | 11 | declare namespace React { 12 | type StatelessComponent

= React.FunctionComponent

; 13 | } 14 | {% endcodeblock %} 15 | 16 | 17 | ### Fixed Code ✔️ 18 | 19 | Make sure to export your additional declaration: 20 | 21 | 22 | {% codeblock lang:ts index.d.ts %} 23 | import * as React from 'react'; 24 | 25 | export declare namespace React { 26 | type StatelessComponent

= React.FunctionComponent

; 27 | } 28 | {% endcodeblock %} 29 | 30 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2403.md: -------------------------------------------------------------------------------- 1 | ## TS2403 2 | 3 | > error TS2403: TS2403: Subsequent variable declarations must have the same type. Variable '`window`' must be of type '`Window & typeof globalThis`', but here has type '`any`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | var window: any = window || null; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | ```ts 14 | var window: Window & typeof globalThis = window || null; 15 | ``` 16 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2411.md: -------------------------------------------------------------------------------- 1 | ## TS2411 2 | 3 | > error TS2411: Property 'age' of type 'number' is not assignable to 'string' index type 'string'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | interface Person { 9 | [key: string]: string; 10 | age: number; 11 | name: string; 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | We defined an interface where every `key` has a value of type `string`. This doesn't work for `age` which is why we have to extend the possible value types using a [**union type**](/glossary/index.html#Union-Types): 18 | 19 | 20 | {% codeblock lang:ts mark:2 %} 21 | interface Person { 22 | [key: string]: number | string; 23 | age: number; 24 | name: string; 25 | } 26 | {% endcodeblock %} 27 | 28 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2420.md: -------------------------------------------------------------------------------- 1 | ## TS2420 2 | 3 | > error TS2420: Class 'Dog' incorrectly implements interface 'Animal'. Property 'name' is private in type 'Dog' but not in type 'Animal'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | interface Animal { 9 | name: string; 10 | } 11 | 12 | class Dog implements Animal { 13 | constructor(private name: string = 'Bobby') {} 14 | } 15 | ``` 16 | 17 | ### Fixed Code ✔️ 18 | 19 | The `Animal` interface defines a public `name` member. The `name` property in our `Dog` class must therefore also be public: 20 | 21 | ```ts 22 | interface Animal { 23 | name: string; 24 | } 25 | 26 | class Dog implements Animal { 27 | constructor(public name: string = 'Bobby') {} 28 | } 29 | ``` 30 | 31 | ### Video Tutorial 32 | 33 | {% youtube 62J_eQsK0e0?start=242 'video' false %} 34 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2428.md: -------------------------------------------------------------------------------- 1 | ## TS2428 2 | 3 | > error TS2428: All declarations of '`Strategy`' must have identical type parameters. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts Strategy.ts %} 9 | enum TOPIC { 10 | ON_LOGOUT = 'ON_LOGOUT', 11 | } 12 | 13 | export interface Strategy { 14 | on(event: TOPIC.ON_LOGOUT, listener: (reason: string) => void): this; 15 | } 16 | 17 | export abstract class Strategy extends EventEmitter { 18 | // ... 19 | } 20 | {% endcodeblock %} 21 | 22 | 23 | ### Fixed Code ✔️ 24 | 25 | Solution: The generic abstract class `Strategy` has a generic type parameter list in angle brackets (diamond notation). This generic type parameter list must also be added to the interface definition of `Strategy`. 26 | 27 | 28 | {% codeblock lang:ts Strategy.ts %} 29 | enum TOPIC { 30 | ON_LOGOUT = 'ON_LOGOUT', 31 | } 32 | 33 | export interface Strategy { 34 | on(event: TOPIC.ON_LOGOUT, listener: (reason: string) => void): this; 35 | } 36 | 37 | export abstract class Strategy extends EventEmitter { 38 | // ... 39 | } 40 | {% endcodeblock %} 41 | 42 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2430.md: -------------------------------------------------------------------------------- 1 | ## TS2430 2 | 3 | > error TS2430: Interface '`StockExchange`' incorrectly extends interface '`Exchange`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | interface Exchange { 9 | address: string; 10 | } 11 | 12 | export interface StockExchange extends Exchange { 13 | address?: string; 14 | } 15 | ``` 16 | 17 | ### Fixed Code ✔ 18 | 19 | The `address` in `Exchange` is a mandatory property but in `StockExchange` it is declared as being optional which creates an incompatibility in the type. To fix the error, the property `address` has either to become optional or mandatory in both declarations: 20 | 21 | ```ts 22 | interface Exchange { 23 | address: string; 24 | } 25 | 26 | export interface StockExchange extends Exchange { 27 | address?: string; 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2440.md: -------------------------------------------------------------------------------- 1 | ## TS2440 2 | 3 | > error TS2440: Import declaration conflicts with local declaration of '`React`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts main.ts %} 9 | import React from 'react'; 10 | 11 | declare module React { 12 | type MyCustomType

= void; 13 | } 14 | {% endcodeblock %} 15 | 16 | 17 | ### Fixed Code ✔️ 18 | 19 | You cannot redeclare a module that you are importing, but you can outsource your additional typings to a declaration file in order to apply **declaration merging**: 20 | 21 | 22 | {% codeblock lang:ts index.d.ts %} 23 | declare namespace React { 24 | type MyCustomType

= void; 25 | } 26 | {% endcodeblock %} 27 | 28 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2445.md: -------------------------------------------------------------------------------- 1 | ## TS2445 2 | 3 | > error TS2445: Property 'makeNoise' is protected and only accessible within class 'Dog' and its subclasses. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | abstract class Animal { 9 | protected abstract makeNoise(): string; 10 | } 11 | 12 | class Dog extends Animal { 13 | protected makeNoise(): string { 14 | return 'Woof!'; 15 | } 16 | } 17 | 18 | const laika = new Dog(); 19 | laika.makeNoise(); 20 | ``` 21 | 22 | ### Fixed Code ✔️ 23 | 24 | The visibility of the `makeNoise` method is protected. We have to make it public if we want to call it directly from an instance of `Dog`: 25 | 26 | 27 | {% codeblock lang:ts mark:6 %} 28 | abstract class Animal { 29 | protected abstract makeNoise(): string; 30 | } 31 | 32 | class Dog extends Animal { 33 | public makeNoise(): string { 34 | return 'Woof!'; 35 | } 36 | } 37 | 38 | const laika = new Dog(); 39 | laika.makeNoise(); 40 | {% endcodeblock %} 41 | 42 | 43 | ### Video Tutorial 44 | 45 | {% youtube 62J_eQsK0e0?start=876 'video' false %} 46 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2448.md: -------------------------------------------------------------------------------- 1 | ## TS2448 2 | 3 | > error TS2448: Block-scoped variable 'add' used before its declaration. 4 | 5 | ### Broken Code ❌ 6 | 7 | **Function expressions** cannot be hoisted (used before they are declared): 8 | 9 | ```ts 10 | add(1, 2); 11 | 12 | const add = (a: number, b: number): number => { 13 | return a + b; 14 | }; 15 | ``` 16 | 17 | ### Fixed Code ✔️ 18 | 19 | Turn your function expression into a **function declaration** (which can be hoisted): 20 | 21 | ```ts 22 | add(1, 2); 23 | 24 | function add(a: number, b: number): number { 25 | return a + b; 26 | } 27 | ``` 28 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2451.md: -------------------------------------------------------------------------------- 1 | ## TS2451 2 | 3 | > error TS2451: Cannot redeclare block-scoped variable '`window`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const window = 'blue'; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | Depending on the configuration of "lib" in your "tsconfig.json" file, there might be global variables that are present (like `window` when using the "dom" library provided by TypeScript). In this case you cannot redeclare the global variable and have to choose another name: 14 | 15 | ```ts 16 | const myWindow = 'blue'; 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2454.md: -------------------------------------------------------------------------------- 1 | ## TS2454 2 | 3 | > error TS2454: Variable 'myFavoriteNumber' is used before being assigned. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export function myNumber(): number { 9 | let myFavoriteNumber: number; 10 | return myFavoriteNumber; 11 | } 12 | ``` 13 | 14 | ### Fixed Code ✔️ 15 | 16 | ```ts 17 | export function myNumber(): number { 18 | let myFavoriteNumber: number; 19 | myFavoriteNumber = 72; 20 | return myFavoriteNumber; 21 | } 22 | ``` 23 | 24 | or 25 | 26 | ```ts 27 | export function myNumber(): number { 28 | let myFavoriteNumber: number = 72; 29 | return myFavoriteNumber; 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2456.md: -------------------------------------------------------------------------------- 1 | ## TS2456 2 | 3 | > error TS2456: Type alias '`MyValue`' circularly references itself. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type MyValue = number | string | Record; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | When defining a recursive type, you have to use the object syntax: 14 | 15 | ```ts 16 | type MyValue = number | string | {[key: string]: MyValue}; 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2459.md: -------------------------------------------------------------------------------- 1 | ## TS2459 2 | 3 | > error TS2459: Module '`./myFunction`' declares '`myFunction`' locally, but it is not exported. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts myFunction.ts %} 9 | function myFunction(a: number, b: number): number { 10 | return a + b; 11 | } 12 | 13 | export {} 14 | {% endcodeblock %} 15 | 16 | 17 | 18 | {% codeblock lang:ts index.ts %} 19 | import {myFunction} from './myFunction'; 20 | 21 | myFunction(1, 2); 22 | {% endcodeblock %} 23 | 24 | 25 | ### Fixed Code ✔️ 26 | 27 | When you want to import your function in another file, you have to make sure that it is exported using the `export` keyword: 28 | 29 | 30 | {% codeblock lang:ts myFunction.ts mark:1 %} 31 | export function myFunction(a: number, b: number): number { 32 | return a + b; 33 | } 34 | {% endcodeblock %} 35 | 36 | 37 | 38 | {% codeblock lang:ts index.ts %} 39 | import {myFunction} from './myFunction'; 40 | 41 | myFunction(1, 2); 42 | {% endcodeblock %} 43 | 44 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2475.md: -------------------------------------------------------------------------------- 1 | ## TS2475 2 | 3 | > error TS2475: 'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment or type query. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export const enum TIME_INTERVAL { 9 | ONE_MINUTE = '1m', 10 | THREE_MINUTES = '3m', 11 | FIVE_MINUTES = '5m', 12 | } 13 | 14 | console.log(Object.values(TIME_INTERVAL)); 15 | ``` 16 | 17 | ### Fixed Code ✔️ 18 | 19 | Defining a `const enum` prevents TypeScript from generating JavaScript code for this enum. With `const enum` TypeScript will just assume that the JavaScript equivalent of this code is already present. 20 | 21 | If you want that TypeScript creates JS code for your enum definition, then you have to remove the `const` keyword: 22 | 23 | ```ts 24 | export enum TIME_INTERVAL { 25 | ONE_MINUTE = '1m', 26 | THREE_MINUTES = '3m', 27 | FIVE_MINUTES = '5m', 28 | } 29 | 30 | console.log(Object.values(TIME_INTERVAL)); 31 | ``` 32 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2476.md: -------------------------------------------------------------------------------- 1 | ## TS2476 2 | 3 | > error TS2476: A const enum member can only be accessed using a string literal. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const enum OrderSide { 9 | BUY = 'buy', 10 | SELL = 'sell', 11 | } 12 | 13 | console.log(OrderSide[0]); 14 | ``` 15 | 16 | ### Fixed Code ✔️ 17 | 18 | Constant enumerations can only be accessed using key names: 19 | 20 | ```ts 21 | const enum OrderSide { 22 | BUY = 'buy', 23 | SELL = 'sell', 24 | } 25 | 26 | console.log(OrderSide.BUY); 27 | ``` 28 | 29 | If you want to access enums by indices, you must remove the `const` keyword and values from your `enum`: 30 | 31 | ```ts 32 | enum OrderSide { 33 | BUY, 34 | SELL, 35 | } 36 | 37 | console.log(OrderSide[0]); 38 | ``` 39 | 40 | ⚠️ Be aware that this may become unsafe as you may unintentionally access indices that are not defined. 41 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2488.md: -------------------------------------------------------------------------------- 1 | ## TS2488 2 | 3 | > error TS2488: Type '`{ [month: number]: string; }`' must have a '`[Symbol.iterator]()`' method that returns an iterator. 4 | 5 | #### Solution 6 | 7 | You have to add a property called `[Symbol.iterator]` to your object. The value of this property has to return an iterator. Here you can {% post_link understanding-generators-iterators-and-iterables 'learn how to create an iterator' %}. 8 | 9 | ### Alternative Solution 10 | 11 | If you run into this problem because of a for-of loop, then you can mitigate the problem by using the `forEach()` method of arrays: 12 | 13 | ### Broken Code ❌ 14 | 15 | ```ts 16 | const months: { 17 | [month: number]: string; 18 | } = { 19 | 1: 'January', 20 | 2: 'February', 21 | }; 22 | 23 | for (const month of months) { 24 | console.log(month); 25 | } 26 | ``` 27 | 28 | ### Fixed Code ✔️ 29 | 30 | ```ts 31 | const months: { 32 | [month: number]: string; 33 | } = { 34 | 1: 'January', 35 | 2: 'February', 36 | }; 37 | 38 | Object.entries(months).forEach(month => { 39 | console.log(month); 40 | }); 41 | ``` 42 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2497.md: -------------------------------------------------------------------------------- 1 | ## TS2497 2 | 3 | > error TS2497: Module '`logdown`' resolves to a non-module entity and cannot be imported using this construct. 4 | 5 | ### Broken Code ❌ 6 | 7 | **Export: logdown.d.ts** 8 | 9 | ```ts 10 | declare class Logdown { 11 | constructor(options?: Object); 12 | public debug(...args: any[]): void; 13 | public error(...args: any[]): void; 14 | public info(...args: any[]): void; 15 | public log(...args: any[]): void; 16 | public warn(...args: any[]): void; 17 | public static disable(...args: string[]): void; 18 | public static enable(...args: string[]): void; 19 | } 20 | 21 | declare module 'logdown' { 22 | export = Logdown; 23 | } 24 | ``` 25 | 26 | **Import: app.ts** 27 | 28 | ```ts 29 | import {Logdown} from 'logdown'; 30 | ``` 31 | 32 | ### Broken Code ❌ #2 33 | 34 | **Export** 35 | 36 | ```ts 37 | declare module 'logdown' { 38 | class Logdown { 39 | constructor(options?: Object); 40 | public debug(...args: any[]): void; 41 | public error(...args: any[]): void; 42 | public info(...args: any[]): void; 43 | public log(...args: any[]): void; 44 | public warn(...args: any[]): void; 45 | public static disable(...args: string[]): void; 46 | public static enable(...args: string[]): void; 47 | } 48 | 49 | export = Logdown; 50 | } 51 | ``` 52 | 53 | **Import** 54 | 55 | ```ts 56 | import {Logdown} from "logdown"; 57 | ... 58 | this.logger = new Logdown({prefix: 'abc', alignOuput: true}); 59 | ``` 60 | 61 | **Note:** TypeScript compiler option "allowSyntheticDefaultImports" must be set to `true`. 62 | 63 | **Import** 64 | 65 | ```ts 66 | import Logdown = require('logdown'); 67 | ``` 68 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2503.md: -------------------------------------------------------------------------------- 1 | ## TS2503 2 | 3 | > error TS2503: Cannot find namespace '`React`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export type CompositeComponent

= React.ComponentClass

; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | You have to add an import statement when reusing a different namespace. Also make sure to install type declarations (i.e. `@types/react`) if needed. 14 | 15 | ```ts 16 | import React from 'react'; 17 | 18 | export type CompositeComponent

= React.ComponentClass

; 19 | ``` 20 | 21 | > error TS2503: Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`. 22 | 23 | ### Solution 24 | 25 | Run `yarn add --dev @types/node` in your npm project. 26 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2507.md: -------------------------------------------------------------------------------- 1 | ## TS2507 2 | 3 | > error TS2507: Type '`typeof EventEmitter`' is not a constructor function type. 4 | 5 | Error happened when importing the exported class in another project. 6 | 7 | ### Broken Code ❌ 8 | 9 | ```ts 10 | import EventEmitter from 'events'; 11 | 12 | export class WebSocketClient extends EventEmitter { 13 | constructor() { 14 | super(); 15 | } 16 | } 17 | ``` 18 | 19 | ### Fixed Code ✔️ 20 | 21 | ```ts 22 | import {EventEmitter} from 'events'; 23 | 24 | export class WebSocketClient extends EventEmitter { 25 | constructor() { 26 | super(); 27 | } 28 | } 29 | ``` 30 | 31 | {% post_link error-ts2307-cannot-find-module-events 'Read more' %} 32 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2511.md: -------------------------------------------------------------------------------- 1 | ## TS2511 2 | 3 | > error TS2511: Cannot create an instance of an abstract class. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | myFunction = (strategyConstructor: typeof Strategy, config: StrategyConfig): Promise => { 9 | // .... 10 | }; 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | ```ts 16 | export interface Type extends Function { 17 | new (...args: any[]): T; 18 | } 19 | 20 | myFunction = (strategyConstructor: StrategyType>, config: StrategyConfig): Promise => { 21 | // .... 22 | }; 23 | ``` 24 | 25 | Read more: [Passing a class constructor](https://stackoverflow.com/questions/12802317/) as parameter to a function. 26 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2512.md: -------------------------------------------------------------------------------- 1 | ## TS2512 2 | 3 | > error TS2512: Overload signatures must all be abstract or non-abstract. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export abstract class MovingAverage { 9 | update(prices: BigSource[]): Big | void; 10 | 11 | abstract update(price: BigSource): Big | void; 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | ```ts 18 | export abstract class MovingAverage { 19 | abstract update(prices: BigSource[]): Big | void; 20 | 21 | abstract update(price: BigSource): Big | void; 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2515.md: -------------------------------------------------------------------------------- 1 | ## TS2515 2 | 3 | > error TS2515: Non-abstract class 'Dog' does not implement inherited abstract member 'makeNoise' from class 'Animal'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | abstract class Animal { 9 | abstract makeNoise(): string; 10 | } 11 | 12 | class Dog extends Animal {} 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | If we derive a class from an abstract class, then we have to provide an implementation for all its `abstract` members: 18 | 19 | ```ts 20 | abstract class Animal { 21 | abstract makeNoise(): string; 22 | } 23 | 24 | class Dog extends Animal { 25 | makeNoise(): string { 26 | return 'Woof!'; 27 | } 28 | } 29 | ``` 30 | 31 | ### Video Tutorial 32 | 33 | {% youtube 62J_eQsK0e0?start=708 'video' false %} 34 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2528.md: -------------------------------------------------------------------------------- 1 | ## TS2528 2 | 3 | > error TS2528: A module cannot have multiple default exports. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const MyPerson = 'Benny'; 9 | 10 | export default MyPerson; 11 | 12 | export default function MyPerson() {} 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | Make sure to only have **one** default export: 18 | 19 | ```ts 20 | const MyPerson = 'Benny'; 21 | 22 | export default MyPerson; 23 | ``` 24 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2531.md: -------------------------------------------------------------------------------- 1 | ## TS2531 2 | 3 | > error TS2531: Object is possibly 'null'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type Person = { 9 | address: { 10 | street: string; 11 | zipCode: number; 12 | } | null; 13 | name: string; 14 | }; 15 | 16 | function logStreet(person: Person): void { 17 | console.log(person.address.street); 18 | } 19 | ``` 20 | 21 | ### Fixed Code ✔️ 22 | 23 | The error originates from the fact that `address` can be `null`. To fix the problem, we can check if `address` is `null` by using **optional chaining**: 24 | 25 | ```ts 26 | type Person = { 27 | address: { 28 | street: string; 29 | zipCode: number; 30 | } | null; 31 | name: string; 32 | }; 33 | 34 | function logStreet(person: Person): void { 35 | console.log(person.address?.street); 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2532.md: -------------------------------------------------------------------------------- 1 | ## TS2532 2 | 3 | > error TS2532: Object is possibly 'undefined'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type Person = { 9 | age: number; 10 | }; 11 | 12 | function logAge(person?: Person): void { 13 | console.log(person.age); 14 | } 15 | ``` 16 | 17 | ### Fixed Code ✔️ 18 | 19 | TypeScript warns us that `person` can be `undefined` (because of the `?`). There are multiple ways to fix the problem. We can do an existence check using an `if`-condition: 20 | 21 | ```ts 22 | type Person = { 23 | age: number; 24 | }; 25 | 26 | function logAge(person?: Person): void { 27 | if (person) { 28 | console.log(person.age); 29 | } 30 | } 31 | ``` 32 | 33 | Alternatively, we can use **optional chaining**: 34 | 35 | ```ts 36 | type Person = { 37 | age: number; 38 | }; 39 | 40 | function logAge(person?: Person): void { 41 | console.log(person?.age); 42 | } 43 | ``` 44 | 45 | Optional chaining is less preferable in this case as it will log `undefined` if the `person` is `undefined`. Using the `if`-condition from the solution above, nothing will be logged to the console in case the `person` is `undefined`. 46 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2533.md: -------------------------------------------------------------------------------- 1 | ## TS2533 2 | 3 | > error TS2533: Object is possibly 'null' or 'undefined'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type Person = { 9 | address?: { 10 | street: string; 11 | zipCode: number; 12 | } | null; 13 | name: string; 14 | }; 15 | 16 | function logStreet(person: Person): void { 17 | console.log(person.address.street); 18 | } 19 | ``` 20 | 21 | ### Fixed Code ✔️ 22 | 23 | The error originates from the fact that `address` can be `undefined` (because of the `?`) or `null`. To fix the problem, we can check if `address` is defined by using **optional chaining**: 24 | 25 | ```ts 26 | type Person = { 27 | address?: { 28 | street: string; 29 | zipCode: number; 30 | } | null; 31 | name: string; 32 | }; 33 | 34 | function logStreet(person: Person): void { 35 | console.log(person.address?.street); 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2538.md: -------------------------------------------------------------------------------- 1 | ## TS2538 2 | 3 | > error TS2538: Type 'Person' cannot be used as an index type. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | interface Person { 9 | name: string; 10 | } 11 | 12 | function getValue(person: Person, key: Person): string { 13 | return person[key]; 14 | } 15 | ``` 16 | 17 | ### Fixed Code ✔️ 18 | 19 | You cannot use an **interface** as an index type, but you can use all keys of the interface using the `keyof` type operator: 20 | 21 | ```ts 22 | interface Person { 23 | name: string; 24 | } 25 | 26 | function getValue(person: Person, key: keyof Person): string { 27 | return person[key]; 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2540.md: -------------------------------------------------------------------------------- 1 | ## TS2540 2 | 3 | > error TS2540: Cannot assign to '`name`' because it is a read-only property. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const user = {name: 'Benny'} as const; 9 | user.name = 'Sofia'; 10 | ``` 11 | 12 | ### Fixed Code ✔️ 13 | 14 | The `user` object has been initialized with a const assertion, indicating to the compiler that the object is immutable. If you wish to reintroduce mutability, you have to remove the const assertion: 15 | 16 | ```ts 17 | const user = {name: 'Benny'}; 18 | user.name = 'Sofia'; 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2550.md: -------------------------------------------------------------------------------- 1 | ## TS2550 2 | 3 | > error TS2550: Property '`setPrototypeOf`' does not exist on type '`ObjectConstructor`'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts code.ts mark:14 %} 9 | type HumanHero = typeof human & typeof hero; 10 | 11 | const human = { 12 | speak: () => { 13 | } 14 | }; 15 | 16 | const hero = { 17 | fly: () => { 18 | } 19 | }; 20 | 21 | // Prototype-based inheritance 22 | Object.setPrototypeOf(hero, human); 23 | {% endcodeblock %} 24 | 25 | 26 | 27 | {% codeblock lang:json tsconfig.json %} 28 | { 29 | "compilerOptions": { 30 | "lib": [ 31 | "dom", 32 | "es5" 33 | ], 34 | "target": "es6" 35 | } 36 | } 37 | {% endcodeblock %} 38 | 39 | 40 | ### Fixed Code ✔️ 41 | 42 | ES5, also known as ECMAScript 2009, doesn't include `Object.setPrototypeOf` which is why you have to upgrade to ES6 (also known as ES2015): 43 | 44 | 45 | {% codeblock lang:json mark:5 tsconfig.json %} 46 | { 47 | "compilerOptions": { 48 | "lib": [ 49 | "dom", 50 | "es6" 51 | ], 52 | "target": "es6" 53 | } 54 | } 55 | {% endcodeblock %} 56 | 57 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2551.md: -------------------------------------------------------------------------------- 1 | ## TS2551 2 | 3 | > error TS2551: Property '`title`' does not exist on type '`Video`'. Did you mean '`titles`'? 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | interface Video { 9 | titles: string; 10 | } 11 | 12 | function showEpisode(this: Video, tag: string) { 13 | console.log(`${this.title} - ${tag}`); 14 | } 15 | ``` 16 | 17 | ### Fixed Code ✔️ 18 | 19 | There is a typo in our code which TypeScript's compiler has caught for us. We have to rename the `titles` property: 20 | 21 | ```ts 22 | interface Video { 23 | title: string; 24 | } 25 | 26 | function showEpisode(this: Video, tag: string) { 27 | console.log(`${this.title} - ${tag}`); 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2552.md: -------------------------------------------------------------------------------- 1 | ## TS2552 2 | 3 | > error TS2552: Cannot find name 'readonlyArray'. Did you mean 'ReadonlyArray'? 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const array: readonlyArray = [1, 2, 3]; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | ```ts 14 | const array: ReadonlyArray = [1, 2, 3]; 15 | ``` 16 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2554.md: -------------------------------------------------------------------------------- 1 | ## TS2554 2 | 3 | > error TS2554: Expected 2 arguments, but got 1. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function printName(firstName: string, lastName: string): void { 9 | console.log(`${firstName} ${lastName}`); 10 | } 11 | 12 | printName('Michael'); 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | ```ts 18 | function printName(firstName: string, lastName: string): void { 19 | console.log(`${firstName} ${lastName}`); 20 | } 21 | 22 | printName('Michael', 'Jordan'); 23 | ``` 24 | 25 | ### Video Tutorial 26 | 27 | {% youtube qF_iZfc22oo?start=191 'video' false %} 28 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2556.md: -------------------------------------------------------------------------------- 1 | ## TS2556 2 | 3 | > error TS2556: A spread argument must either have a tuple type or be passed to a rest parameter. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function sum(a: number, b: number): number { 9 | return a + b; 10 | } 11 | 12 | console.log(sum(1, ...[2, 3, 4, 5])); 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | When calling a function using the spread syntax (`...`), we have to ensure that the called function uses a rest parameter: 18 | 19 | ```ts 20 | function sum(a: number, ...b: number[]): number { 21 | return a + b.reduce((c, d) => c + d); 22 | } 23 | 24 | console.log(sum(1, ...[2, 3, 4, 5])); 25 | ``` 26 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2558.md: -------------------------------------------------------------------------------- 1 | ## TS2558 2 | 3 | > error TS2558: Expected 2 type arguments, but got 1. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts %} 9 | function combine(a: X, b: Y): (X | Y)[] { 10 | return [a, b]; 11 | } 12 | 13 | combine(1, '2'); 14 | {% endcodeblock %} 15 | 16 | 17 | ### Fixed Code ✔️ 18 | 19 | The `combine` function defines 2 **type variables** (`X` & `Y`), so you have to pass it 2 **type arguments**: 20 | 21 | 22 | {% codeblock lang:ts mark:5 %} 23 | function combine(a: X, b: Y): (X | Y)[] { 24 | return [a, b]; 25 | } 26 | 27 | combine(1, '2'); 28 | {% endcodeblock %} 29 | 30 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2559.md: -------------------------------------------------------------------------------- 1 | ## TS2559 2 | 3 | > error TS2559: Type '`{ city: string; }`' has no properties in common with type '`User`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts %} 9 | interface User { 10 | age?: number; 11 | name?: string; 12 | } 13 | 14 | function increaseAge(user: User): void { 15 | if (user.age) { 16 | user.age += 1; 17 | } 18 | } 19 | 20 | const user = {city: 'Berlin'}; 21 | 22 | increaseAge(user); 23 | {% endcodeblock %} 24 | 25 | 26 | ### Fixed Code ✔️ 27 | 28 | The problem occurs with **weak types** (in this case `User`). All properties of a weak type are optional but when your input doesn't match any of the properties, you will get to see error **TS2559**. To fix it you have to match at least one of the optional properties: 29 | 30 | 31 | {% codeblock lang:ts mark:11 %} 32 | interface User { 33 | age?: number; 34 | name?: string; 35 | } 36 | 37 | function increaseAge(user: User): void { 38 | if (user.age) { 39 | user.age += 1; 40 | } 41 | } 42 | 43 | const user = {age: 1, city: 'Berlin'}; 44 | 45 | increaseAge(user); 46 | {% endcodeblock %} 47 | 48 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2564.md: -------------------------------------------------------------------------------- 1 | ## TS2564 2 | 3 | > error TS2564: Property 'name' has no initializer and is not definitely assigned in the constructor. 4 | 5 | This error can occur with TypeScript 2.7 in "strict" mode. TypeScript 2.7 introduced a new flag called `--strictPropertyInitialization`, which tells the compiler to check that each instance property of a class gets initialized in the constructor body, or by a property initializer. See [Strict Class Initialization](https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#strict-class-initialization). 6 | 7 | ### Broken Code ❌ 8 | 9 | ```ts 10 | class Dog { 11 | private name: string; 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | We have to initialize the `name` member either at its definition or within the `constructor`. 18 | 19 | Solution 1: 20 | 21 | ```ts 22 | class Dog { 23 | private name: string = 'Laika'; 24 | } 25 | ``` 26 | 27 | Solution 2: 28 | 29 | ```ts 30 | class Dog { 31 | private name: string; 32 | 33 | constructor() { 34 | this.name = 'Laika'; 35 | } 36 | } 37 | ``` 38 | 39 | Solution 3: 40 | 41 | ```ts 42 | class Dog { 43 | constructor(private name: string = 'Laika') {} 44 | } 45 | ``` 46 | 47 | ### Video Tutorial 48 | 49 | {% youtube 62J_eQsK0e0?start=401 'video' false %} 50 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2567.md: -------------------------------------------------------------------------------- 1 | ## TS2567 2 | 3 | > error TS2567: Enum declarations can only merge with namespace or other enum declarations. `lib.dom.d.ts(18299, 6)`: 'ResponseType' was also declared here. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | enum ResponseType { 9 | ACTIVE, 10 | ERROR, 11 | } 12 | ``` 13 | 14 | ### Fixed Code ✔️ 15 | 16 | In the broken code shown above, a `type ResponseType` is already declared as part of the "dom" typings. Enums can be merged with other enums but since the other declaration of `ResponseType` is a `type`, we cannot merge the existing declaration with our custom one. That's why we have to remove "dom" from the "lib" entries in our "tsconfig.json" file or use a different name for our `enum`: 17 | 18 | ```ts 19 | enum MyResponseType { 20 | ACTIVE, 21 | ERROR, 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2571.md: -------------------------------------------------------------------------------- 1 | ## TS2571 2 | 3 | > error TS2571: Object is of type 'unknown'. 4 | 5 | ### Broken Code ❌ 6 | 7 | If you use third-party libraries then it can happen that TypeScript cannot infer all return types. In such a case a return type can be `unknown` which makes it impossible to access its properties from TypeScript. In the following example such case is constructed by assigning `unknown` to an exemplary constant: 8 | 9 | ```ts 10 | const x: unknown = 1337; 11 | console.log(x.toString()); 12 | ``` 13 | 14 | ### Fixed Code ✔️ 15 | 16 | To solve the problem of accessing properties from an unknown object, we have to define the type of the object which we want to access: 17 | 18 | ```ts 19 | const x: number = 1337; 20 | console.log(x.toString()); 21 | ``` 22 | 23 | ### Broken Code ❌ 24 | 25 | ```ts 26 | export const hasUsers = (payload: unknown): payload is {users: string[]} => { 27 | return 'users' in payload; 28 | }; 29 | ``` 30 | 31 | ### Fixed Code ✔️ 32 | 33 | If your variable is of type `unknown`, then you can use a **type guard** to narrow the type of your variable. If you want to be sure that you have an object at hand, you can use the `typeof` type guard: 34 | 35 | ```ts 36 | export const hasUsers = (payload: unknown): payload is {users: string[]} => { 37 | if (payload && typeof payload === 'object') { 38 | return 'users' in payload; 39 | } 40 | return false; 41 | }; 42 | ``` 43 | 44 | ### Alternative 45 | 46 | You may also get the error "Object is of type 'unknown'" when catching errors. In this case you have to [type the error in your catch clause](https://www.youtube.com/watch?v=0GLYiJUBz6k). 47 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2574.md: -------------------------------------------------------------------------------- 1 | ## TS2574 2 | 3 | > error TS2574: A rest element type must be an array type. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type Operation = '+' | '-'; 9 | 10 | type Calculation = [Operation, ...number]; 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | Simply turn `...number` into `...number[]`: 16 | 17 | ```ts 18 | type Operation = '+' | '-'; 19 | 20 | type Calculation = [Operation, ...number[]]; 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2577.md: -------------------------------------------------------------------------------- 1 | ## TS2577 2 | 3 | > error TS2577: Return type annotation circularly references itself. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type OurReply = ReturnType; 9 | 10 | function reply(text: string): OurReply { 11 | if (text === 'Hello') { 12 | return 'Hi!'; 13 | } 14 | 15 | if (text === 'Goodbye') { 16 | return 'Bye!'; 17 | } 18 | 19 | return "What's up?"; 20 | } 21 | ``` 22 | 23 | ### Fixed Code ✔️ 24 | 25 | You can remove the circular reference by removing the explicit return type (`OurReply`) from the signature of your function: 26 | 27 | 28 | {% codeblock lang:ts mark:3 %} 29 | type OurReply = ReturnType; 30 | 31 | function reply(text: string) { 32 | if (text === "Hello") { 33 | return "Hi!"; 34 | } 35 | 36 | if (text === "Goodbye") { 37 | return "Bye!"; 38 | } 39 | 40 | return "What's up?"; 41 | } 42 | {% endcodeblock %} 43 | 44 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2580.md: -------------------------------------------------------------------------------- 1 | ## TS2580 2 | 3 | > error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const path = require('path'); 9 | console.log(path.basename(__dirname)); 10 | ``` 11 | 12 | ### Fixed Code ✔️ 13 | 14 | Install typings for Node.js: 15 | 16 | ```bash 17 | npm i --save-dev @types/node 18 | ``` 19 | 20 | Update code to modern import syntax: 21 | 22 | ```ts 23 | import path from 'path'; 24 | console.log(path.basename(__dirname)); 25 | ``` 26 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2582.md: -------------------------------------------------------------------------------- 1 | ## TS2582 2 | 3 | > error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i --save-dev @types/jest` or `npm i --save-dev @types/mocha`. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | test('create sum', () => { 9 | expect(1 + 2).toBe(3); 10 | }); 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | The error above is very specific to your testing framework and when using [Jest](https://jestjs.io/) it can be easily solved by installing definition files for Jest (`npm i --save-dev @types/jest`). 16 | 17 | When you are using [Playwright](https://playwright.dev/), then you would have to make sure that you properly import Playwright's definition for `test`: 18 | 19 | ```ts 20 | import {test, expect} from '@playwright/test'; 21 | 22 | test('create sum', () => { 23 | expect(1 + 2).toBe(3); 24 | }); 25 | ``` 26 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2583.md: -------------------------------------------------------------------------------- 1 | ## TS2583 2 | 3 | > error TS2583: Cannot find name 'BigInt'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2020' or later. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:json tsconfig.json %} 9 | { 10 | "compilerOptions": { 11 | "lib": [ 12 | "dom" 13 | ] 14 | } 15 | } 16 | {% endcodeblock %} 17 | 18 | 19 | 20 | {% codeblock ImmortalPerson.ts lang:ts %} 21 | type ImmortalPerson = { 22 | age: BigInt; 23 | } 24 | {% endcodeblock %} 25 | 26 | 27 | ### Fixed Code ✔️ 28 | 29 | [Arbitrary-precision integers (BigInt)](https://tc39.es/proposal-bigint/) were introduced in 11th edition of the ECMAScript Language Specification (ES11 / ES2020), so you have to add this information to the "lib" property of your TypeScript configuration to make use of this API: 30 | 31 | 32 | {% codeblock lang:json tsconfig.json mark:5 %} 33 | { 34 | "compilerOptions": { 35 | "lib": [ 36 | "dom", 37 | "es2020.bigint" 38 | ] 39 | } 40 | } 41 | {% endcodeblock %} 42 | 43 | 44 | Alternatively, you can make all additional APIs from ES2020 available to your code: 45 | 46 | 47 | {% codeblock lang:json tsconfig.json mark:5 %} 48 | { 49 | "compilerOptions": { 50 | "lib": [ 51 | "dom", 52 | "es2020" 53 | ] 54 | } 55 | } 56 | {% endcodeblock %} 57 | 58 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2584.md: -------------------------------------------------------------------------------- 1 | ## TS2584 2 | 3 | > error TS2584: Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'. 4 | 5 | ### Broken Code ❌ 6 | 7 | TypeScript code: 8 | 9 | ```ts 10 | console.log('Hello, World!'); 11 | ``` 12 | 13 | TypeScript compiler configuration (`tsconfig.json`): 14 | 15 | ```json 16 | { 17 | "compilerOptions": { 18 | "lib": ["es2017"] 19 | } 20 | } 21 | ``` 22 | 23 | ### Fixed Code ✔️ 24 | 25 | You have to add the following to your "tsconfig.json" file: 26 | 27 | ```json 28 | { 29 | "compilerOptions": { 30 | "lib": ["es2017", "dom"] 31 | } 32 | } 33 | ``` 34 | 35 | When you are working on an application which never runs in a browser but only in Node.js environments, then you could add `@types/node` to your `devDependencies` instead of adding `"dom"` to your `"lib"` section. 36 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2588.md: -------------------------------------------------------------------------------- 1 | ## TS2588 2 | 3 | > error TS2588: Cannot assign to 'name' because it is a constant. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const name = 'Benny'; 9 | name = 'Sofia'; 10 | ``` 11 | 12 | ### Fixed Code ✔️ 13 | 14 | You cannot reassign values to **constants** which is why you have to declare a **variable** using the `let` keyword: 15 | 16 | ```ts 17 | let name = 'Benny'; 18 | name = 'Sofia'; 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2595.md: -------------------------------------------------------------------------------- 1 | ## TS2595 2 | 3 | > error TS2595: '`React`' can only be imported by using a default import. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import {React} from 'react'; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | A **default import** cannot be put in curly braces: 14 | 15 | ```ts 16 | import React from 'react'; 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2611.md: -------------------------------------------------------------------------------- 1 | ## TS2611 2 | 3 | > error TS2611: '`name`' is defined as a property in class '`Person`', but is overridden here in '`MyPerson`' as an accessor. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | abstract class Person { 9 | name: string = 'unknown'; 10 | } 11 | 12 | class MyPerson extends Person { 13 | get name(): string { 14 | return `${super.name.toUpperCase}`; 15 | } 16 | } 17 | ``` 18 | 19 | Getters and setters are property accessors, so you have to make sure that you don't mix **property** definitions with **property accessor** definitions. Using the `accessor` keyword, you can turn a property into a property accessor: 20 | 21 | ```ts 22 | abstract class Person { 23 | accessor name: string = 'unknown'; 24 | } 25 | 26 | class MyPerson extends Person { 27 | get name(): string { 28 | return `${super.name.toUpperCase}`; 29 | } 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2613.md: -------------------------------------------------------------------------------- 1 | ## TS2613 2 | 3 | > error TS2613: Module '`add`' has no default export. Did you mean to use '`import { add } from "add"`' instead? 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock add.ts lang:ts %} 9 | export function add(a: number, b: number): number { 10 | return a + b; 11 | } 12 | {% endcodeblock %} 13 | 14 | 15 | 16 | {% codeblock main.ts lang:ts %} 17 | import add from './add'; 18 | 19 | console.log(add(1000, 337)); 20 | {% endcodeblock %} 21 | 22 | 23 | ### Fixed Code ✔️ 24 | 25 | To fix the bug we have to convert our named export into a **default export**: 26 | 27 | 28 | {% codeblock add.ts lang:ts %} 29 | export default function add(a: number, b: number): number { 30 | return a + b; 31 | } 32 | {% endcodeblock %} 33 | 34 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2616.md: -------------------------------------------------------------------------------- 1 | ## TS2616 2 | 3 | > error TS2616: 'React' can only be imported by using 'import React = require("react")' or a default import. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```tsx 8 | import {React, FC} from 'react'; 9 | 10 | const App: FC = (): JSX.Element => { 11 | return <>; 12 | }; 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | Use default import for React: 18 | 19 | ```tsx 20 | import React, {FC} from 'react'; 21 | 22 | const App: FC = (): JSX.Element => { 23 | return <>; 24 | }; 25 | ``` 26 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2636.md: -------------------------------------------------------------------------------- 1 | ## TS2636 2 | 3 | > error TS2636: Type '`Func`' is not assignable to type '`Func`' as implied by variance annotation. Type '`super-T`' is not assignable to type '`sub-T`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type Func = () => T; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | Variance annotations on type variables must be consistent with their position. If a type variable is at output (read) position, it should be annotated with `out`: 14 | 15 | ```ts 16 | type Func = () => T; 17 | ``` 18 | 19 | Alternatively, you can annotate it with both `in` and `out` (i.e. as invariant): 20 | 21 | ```ts 22 | type Func = () => T; 23 | ``` 24 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2637.md: -------------------------------------------------------------------------------- 1 | ## TS2637 2 | 3 | > error TS2637: Variance annotations are only supported in type aliases for object, function, constructor, and mapped types. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type Pair = [T, T]; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | Variance annotations only make sense if variance is considered while resolving the type alias. Since tuples and arrays are always type-checked covariantly, they do nothing in this case and thus raise the error. 14 | 15 | To resolve the error, simply remove the variance annotation. 16 | 17 | ```ts 18 | type Pair = [T, T]; 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2652.md: -------------------------------------------------------------------------------- 1 | ## TS2652 2 | 3 | > error TS2652: Merged declaration '`MyPerson`' cannot include a default export declaration. Consider adding a separate '`export default MyPerson`' declaration instead. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const MyPerson = 'Benny'; 9 | 10 | export default function MyPerson() { 11 | // 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | You cannot use the same name to declare a constant and a function. If your intention is to export your constant, then do the following: 18 | 19 | ```ts 20 | const MyPerson = 'Benny'; 21 | 22 | export default MyPerson; 23 | ``` 24 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2654.md: -------------------------------------------------------------------------------- 1 | ## TS2654 2 | 3 | > error TS2654: Exported external package typings file cannot contain tripleslash references. Please contact the package author to update the package definition. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | /// 9 | ``` 10 | 11 | ### Fix 12 | 13 | - Remove `/// ` in `.d.ts` files 14 | 15 | ### Video Tutorial 16 | 17 | {% youtube 62J_eQsK0e0?start=401 'video' false %} 18 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2656.md: -------------------------------------------------------------------------------- 1 | ## TS2656 2 | 3 | > error TS2656: Exported external package typings file '`../proteus.d.ts`' is not a module. Please contact the package author to update the package definition. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock proteus.d.ts lang:ts %} 9 | declare module Proteus { 10 | } 11 | {% endcodeblock %} 12 | 13 | 14 | ### Fixed Code ✔️ 15 | 16 | 17 | {% codeblock proteus.d.ts lang:ts %} 18 | export module Proteus { 19 | } 20 | {% endcodeblock %} 21 | 22 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2661.md: -------------------------------------------------------------------------------- 1 | ## TS2661 2 | 3 | > error TS2661: Cannot export '`getSdk`'. Only local declarations can be exported from a module. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts index.ts %} 9 | export {getSdk}; 10 | {% endcodeblock %} 11 | 12 | 13 | 14 | {% codeblock lang:ts getSdk.ts %} 15 | function getSdk() {} 16 | {% endcodeblock %} 17 | 18 | 19 | ### Fixed Code ✔️ 20 | 21 | If you want to re-export `getSdk` in another file, you have to export it first from its origin and then import it in the file where you want to re-export it: 22 | 23 | 24 | {% codeblock lang:ts index.ts mark:1 %} 25 | import {getSdk} from './getSdk'; 26 | 27 | export {getSdk}; 28 | {% endcodeblock %} 29 | 30 | 31 | 32 | {% codeblock lang:ts getSdk.ts mark:1 %} 33 | export function getSdk() {} 34 | {% endcodeblock %} 35 | 36 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2663.md: -------------------------------------------------------------------------------- 1 | ## TS2663 2 | 3 | > error TS2663: Cannot find name '`firstName`'. Did you mean the instance member '`this.firstName`'? 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | class Person { 9 | get firstName(): string { 10 | return firstName; 11 | } 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | If you want to use a **getter**, you need to back it up with a private property: 18 | 19 | ```ts 20 | class Person { 21 | private _firstName: string = ''; 22 | 23 | get firstName(): string { 24 | return this._firstName; 25 | } 26 | } 27 | ``` 28 | 29 | Starting from TypeScript 4.9, you can also use an [auto-accessor](https://github.com/microsoft/TypeScript/pull/49705) field: 30 | 31 | ```ts 32 | class Person { 33 | accessor firstName: string = ''; 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2664.md: -------------------------------------------------------------------------------- 1 | ## TS2664 2 | 3 | > error TS2664: Invalid module name in augmentation, module '`gas-local`' cannot be found. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock main.ts lang:ts %} 9 | declare module "gas-local"; 10 | {% endcodeblock %} 11 | 12 | 13 | ### Fixed Code ✔️ 14 | 15 | The problem occurs when you want to write a **module augmentation** for a package that isn't found in your "node_modules" directory. Make sure to install the module: 16 | 17 | ```bash 18 | npm install gas-local --save 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2665.md: -------------------------------------------------------------------------------- 1 | ## TS2665 2 | 3 | > error TS2665: Invalid module name in augmentation. Module '`gas-local`' resolves to an untyped module at '`../node_modules/gas-local/index.js`', which cannot be augmented. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock main.ts lang:ts %} 9 | declare module "gas-local"; 10 | import gas from 'gas-local'; 11 | 12 | const glib = gas.require('./src'); 13 | {% endcodeblock %} 14 | 15 | 16 | ### Fixed Code ✔️ 17 | 18 | You have to move the **shorthand ambient module declaration** from a ".ts" file into a ".d.ts" file: 19 | 20 | 21 | {% codeblock types.d.ts lang:ts %} 22 | declare module "gas-local"; 23 | {% endcodeblock %} 24 | 25 | 26 | 27 | {% codeblock main.ts lang:ts %} 28 | import gas from 'gas-local'; 29 | 30 | const glib = gas.require('./src'); 31 | {% endcodeblock %} 32 | 33 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2668.md: -------------------------------------------------------------------------------- 1 | ## TS2668 2 | 3 | > error TS2668: 'export' modifier cannot be applied to ambient modules and module augmentations since they are always visible. 4 | 5 | ### Info 6 | 7 | **Ambient modules** 8 | 9 | To describe the shape of libraries not written in TypeScript, we need to declare the API that the library exposes. We call declarations that don’t define an implementation “**ambient**”. Typically, these are defined in `.d.ts` files. If you’re familiar with C/C++, you can think of these as `.h` files. 10 | 11 | Source: https://www.typescriptlang.org/docs/handbook/modules.html 12 | 13 | **Module Augmentation** 14 | 15 | With module augmentation, users have the ability to extend existing modules such that consumers can specify if they want to import the whole module or just a subset. 16 | 17 | Source: https://blogs.msdn.microsoft.com/typescript/2016/02/22/announcing-typescript-1-8-2/ 18 | 19 | ### Broken Code ❌ 20 | 21 | ```ts 22 | export module 'amplify' { 23 | export function publish(topic: string, ...args: any[]): boolean; 24 | } 25 | ``` 26 | 27 | ### Fixed Code ✔️ 28 | 29 | ```ts 30 | export function publish(topic: string, ...args: any[]): boolean; 31 | ``` 32 | 33 | ### Usage 34 | 35 | ```ts 36 | import amplify = require('amplify'); 37 | ``` 38 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2669.md: -------------------------------------------------------------------------------- 1 | ## TS2669 2 | 3 | > error TS2669: Augmentations for the global scope can only be directly nested in external modules or ambient module declarations. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | declare global { 9 | namespace NodeJS { 10 | interface Global { 11 | __coverage__: {}; 12 | } 13 | } 14 | } 15 | ``` 16 | 17 | You have to turn your code into a module by adding an `import` or `export` statement to your code. The easiest way to solve the problem is exporting an empty object: 18 | 19 | ### Fixed Code ✔️ 20 | 21 | ```ts 22 | declare global { 23 | namespace NodeJS { 24 | interface Global { 25 | __coverage__: {}; 26 | } 27 | } 28 | } 29 | 30 | export {}; 31 | ``` 32 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2677.md: -------------------------------------------------------------------------------- 1 | ## TS2677 2 | 3 | > error TS2677: A type predicate's type must be assignable to its parameter's type. Type '`number`' is not assignable to type '`string`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const isInteger = (input: string): input is number => { 9 | return !!parseInt(input, 10); 10 | }; 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | The `input` is declared to be of type `string` which is why the **type predicate** cannot turn it into a `number` because these two declarations are mutually exclusive. That's why we have to declare an input type of `any`: 16 | 17 | ```ts 18 | const isInteger = (input: any): input is number => { 19 | return !!parseInt(input, 10); 20 | }; 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2678.md: -------------------------------------------------------------------------------- 1 | ## TS2678 2 | 3 | > error TS2678: Type '`StreamStatus`' is not comparable to type '`number`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | enum StreamStatus { 9 | ONLINE = 'ONLINE', 10 | OFFLINE = 'OFFLINE', 11 | } 12 | 13 | interface StreamResponse { 14 | status: number; 15 | } 16 | 17 | function handleResponse(response: StreamResponse): void { 18 | switch (response.status) { 19 | case StreamStatus.ONLINE: 20 | console.log('You are online.'); 21 | break; 22 | case StreamStatus.OFFLINE: 23 | console.log('You are offline.'); 24 | break; 25 | } 26 | } 27 | ``` 28 | 29 | ### Fixed Code ✔️ 30 | 31 | The `StreamResponse` declares a "status" property of type `number` but the switch-case statement checks against `StreamStatus`, so we have to adjust the typing for "status" of `StreamResponse`: 32 | 33 | ```ts 34 | enum StreamStatus { 35 | ONLINE = 'ONLINE', 36 | OFFLINE = 'OFFLINE', 37 | } 38 | 39 | interface StreamResponse { 40 | status: StreamStatus; 41 | } 42 | 43 | function handleResponse(response: StreamResponse): void { 44 | switch (response.status) { 45 | case StreamStatus.ONLINE: 46 | console.log('You are online.'); 47 | break; 48 | case StreamStatus.OFFLINE: 49 | console.log('You are offline.'); 50 | break; 51 | } 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2680.md: -------------------------------------------------------------------------------- 1 | ## TS2680 2 | 3 | > error TS2680: A 'this' parameter must be the first parameter. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type Person = { 9 | name: string; 10 | }; 11 | 12 | export function sayHello(text: string = 'Hello', this: Person): void { 13 | console.log(`${text} ${this.name}`); 14 | } 15 | ``` 16 | 17 | ### Fixed Code ✔️ 18 | 19 | TypeScript requires that a `this` parameter always comes first in the list of parameters: 20 | 21 | ```ts 22 | type Person = { 23 | name: string; 24 | }; 25 | 26 | export function sayHello(this: Person, text: string = 'Hello'): void { 27 | console.log(`${text} ${this.name}`); 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2683.md: -------------------------------------------------------------------------------- 1 | ## TS2683 2 | 3 | > error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export function sayHello(text: string = 'Hello'): void { 9 | console.log(`${text} ${this.name}`); 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | This bug is also a consequence of [TS2680](#TS2680). To fix the bug we have to define the context of our function. It can be done by defining `this` as the first parameter in our argument list and giving it a type annotation: 16 | 17 | ```ts 18 | type Person = { 19 | name: string; 20 | }; 21 | 22 | export function sayHello(this: Person, text: string = 'Hello'): void { 23 | console.log(`${text} ${this.name}`); 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2684.md: -------------------------------------------------------------------------------- 1 | ## TS2684 2 | 3 | > error TS2684: The '`this`' context of type '`void`' is not assignable to method's '`this`' of type '`Person`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type Person = { 9 | name: string; 10 | }; 11 | 12 | export function sayHello(this: Person, text: string = 'Hello'): void { 13 | console.log(`${text} ${this.name}`); 14 | } 15 | 16 | sayHello('Welcome'); 17 | ``` 18 | 19 | ### Fixed Code ✔️ 20 | 21 | When calling a function that defines a `this` parameter, then we have to set the `this` context with `apply`, `bind` or `call`. 22 | 23 | **Using `apply`:** 24 | 25 | ```ts 26 | type Person = { 27 | name: string; 28 | }; 29 | 30 | export function sayHello(this: Person, text: string = 'Hello'): void { 31 | console.log(`${text} ${this.name}`); 32 | } 33 | 34 | const benny: Person = { 35 | name: 'Benny', 36 | }; 37 | 38 | sayHello.apply(benny, ['Welcome']); 39 | ``` 40 | 41 | **Using `bind`:** 42 | 43 | ```ts 44 | type Person = { 45 | name: string; 46 | }; 47 | 48 | export function sayHello(this: Person, text: string = 'Hello'): void { 49 | console.log(`${text} ${this.name}`); 50 | } 51 | 52 | const benny: Person = { 53 | name: 'Benny', 54 | }; 55 | 56 | sayHello.bind(benny)('Welcome'); 57 | ``` 58 | 59 | **Using `call`:** 60 | 61 | ```ts 62 | type Person = { 63 | name: string; 64 | }; 65 | 66 | export function sayHello(this: Person, text: string = 'Hello'): void { 67 | console.log(`${text} ${this.name}`); 68 | } 69 | 70 | const benny: Person = { 71 | name: 'Benny', 72 | }; 73 | 74 | sayHello.call(benny, 'Welcome'); 75 | ``` 76 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2686.md: -------------------------------------------------------------------------------- 1 | ## TS2686 2 | 3 | > error TS2686: 'ko' refers to a UMD global, but the current file is a module. Consider adding an import instead. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const downloadProgress = ko.observable(); 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | ```ts 14 | import ko from 'knockout'; 15 | 16 | const downloadProgress = ko.observable(); 17 | ``` 18 | 19 | > TS2686: 'sinon' refers to a UMD global, but the current file is a module. Consider adding an import instead. 20 | 21 | ### Broken Code ❌ 22 | 23 | ```ts 24 | import {SinonFakeServer} from 'sinon'; 25 | let server: SinonFakeServer; 26 | ``` 27 | 28 | ### Fixed Code ✔️ 29 | 30 | ```ts 31 | import * as sinon from 'sinon'; 32 | let server: sinon.SinonFakeServer; 33 | ``` 34 | 35 | > TS2686: 'React' refers to a UMD global, but the current file is a module. Consider adding an import instead. 36 | 37 | ### Broken Code ❌ 38 | 39 | ```tsx 40 | import {FC} from 'react'; 41 | 42 | const App: FC = (): JSX.Element => { 43 | return <>; 44 | }; 45 | ``` 46 | 47 | ### Fixed Code ✔️ 48 | 49 | Use default import for React: 50 | 51 | ```tsx 52 | import React from 'react'; 53 | 54 | const App: React.FC = (): JSX.Element => { 55 | return <>; 56 | }; 57 | ``` 58 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2687.md: -------------------------------------------------------------------------------- 1 | ## TS2687 2 | 3 | > error TS2687: All declarations of 'status' must have identical modifiers. `lib.dom.d.ts(11620, 14)`: '`status`' was also declared here. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | interface Response { 9 | data?: string; 10 | status: StreamStatus; 11 | } 12 | ``` 13 | 14 | ### Fixed Code ✔️ 15 | 16 | In the error above, a `Response` is declared which should be merged (using declaration merging) with the `Response` interface of the "dom" library which is set in "lib" within the "tsconfig.json" file. When merging with an existing declaration, the property types of the first declaration must be matched because you can only add additional properties when using declaration merging. The same rules applies to **modifiers**. Because "status" has a readonly modifier in the existing `Response` interface, we must declare the same in our own interface extension: 17 | 18 | ```ts 19 | interface Response { 20 | data?: string; 21 | readonly status: number; 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2689.md: -------------------------------------------------------------------------------- 1 | ## TS2689 2 | 3 | > error TS2689: Cannot extend an interface 'Animal'. Did you mean 'implements'? 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | interface Animal { 9 | name: string; 10 | } 11 | 12 | class Dog extends Animal { 13 | name = 'Default Dog'; 14 | } 15 | ``` 16 | 17 | ### Fixed Code ✔️ 18 | 19 | The TypeScript compiler tells us already the solution: When implementing an interface, we have to use `implements`. If we inherit from classes, we use `extends`. 20 | 21 | ```ts 22 | class Dog extends Animal { 23 | protected makeNoise(): string { 24 | return 'Woof!'; 25 | } 26 | } 27 | ``` 28 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2691.md: -------------------------------------------------------------------------------- 1 | ## TS2691 2 | 3 | > error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing './index' instead. 4 | 5 | ### Broken Code ❌ 6 | 7 | You cannot directly import code from **declaration files**: 8 | 9 | ```ts 10 | import {myFunction} from './index.d.ts'; 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | You have to import functions from the source code file (e.g. `index.ts`): 16 | 17 | ```ts 18 | import {myFunction} from './index'; 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2693.md: -------------------------------------------------------------------------------- 1 | ## TS2693 2 | 3 | > error TS2693: '`Candlestick`' only refers to a type, but is being used as a value here. 4 | 5 | ### Broken Code ❌ 6 | 7 | **main.ts** 8 | 9 | ```ts 10 | import Candlestick from '../../chart/Candlestick'; 11 | const candle = new Candlestick(); 12 | ``` 13 | 14 | **Candlestick.ts** 15 | 16 | ```ts 17 | interface Candlestick { 18 | close: number; 19 | high: number; 20 | low: number; 21 | open: number; 22 | } 23 | 24 | export default Candlestick; 25 | ``` 26 | 27 | ### Fixed Code ✔️ 28 | 29 | **main.ts** 30 | 31 | ```ts 32 | import Candlestick from '../../chart/Candlestick'; 33 | const candle = new Candlestick(); 34 | ``` 35 | 36 | **Candlestick.ts** 37 | 38 | ```ts 39 | class Candlestick { 40 | close: number = 0; 41 | high: number = 0; 42 | low: number = 0; 43 | open: number = 0; 44 | } 45 | 46 | export default Candlestick; 47 | ``` 48 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2694.md: -------------------------------------------------------------------------------- 1 | ## TS2694 2 | 3 | > error TS2694: Namespace '`React`' has no exported member '`NonExistent`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import React from 'react'; 9 | 10 | export type CompositeComponent

= React.NonExistent

; 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | When trying to import a type that is missing in an external namespace, then you have to add the missing typings yourself: 16 | 17 | ```ts 18 | import React from 'react'; 19 | 20 | declare global { 21 | namespace React { 22 | type NonExistent

= React.FunctionComponent

; 23 | } 24 | } 25 | 26 | export type CompositeComponent

= React.NonExistent

; 27 | ``` 28 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2695.md: -------------------------------------------------------------------------------- 1 | ## TS2695 2 | 3 | > error TS2695: Left side of comma operator is unused and has no side effects. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import express from 'express'; 9 | 10 | const app = express(); 11 | 12 | app.use((, res, next) => { 13 | res.header('Access-Control-Allow-Origin', '*'); 14 | next(); 15 | }); 16 | ``` 17 | 18 | ### Fixed Code ✔️ 19 | 20 | You just cannot leave out a callback parameter if you don't want to use it. Mark it with an underscore (`_`) instead: 21 | 22 | ```ts 23 | import express from 'express'; 24 | 25 | const app = express(); 26 | 27 | app.use((_, res, next) => { 28 | res.header('Access-Control-Allow-Origin', '*'); 29 | next(); 30 | }); 31 | ``` 32 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2706.md: -------------------------------------------------------------------------------- 1 | ## TS2706 2 | 3 | > error TS2706: Required type parameters may not follow optional type parameters. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | class KeyValuePair { 9 | key: Key | undefined; 10 | value: Value | undefined; 11 | } 12 | 13 | const populationFigures = new KeyValuePair(); 14 | ``` 15 | 16 | ### Fixed Code ✔️ 17 | 18 | The generic type `Key` is defined with a default value of `string` which makes this type parameter not optional. However, the `Value` type parameter is optional and optional parameters are not allowed to follow required parameters. 19 | 20 | To solve the situation, we have can switch the position of the two parameters which would impact how we use the code: 21 | 22 | 23 | {% codeblock lang:ts mark:1,6 %} 24 | class KeyValuePair { 25 | key: Key | undefined; 26 | value: Value | undefined; 27 | } 28 | 29 | const populationFigures = new KeyValuePair(); 30 | {% endcodeblock %} 31 | 32 | 33 | Alternatively, we can also set a default type for `Value`: 34 | 35 | 36 | {% codeblock lang:ts mark:1 %} 37 | class KeyValuePair { 38 | key: Key | undefined; 39 | value: Value | undefined; 40 | } 41 | 42 | const populationFigures = new KeyValuePair(); 43 | {% endcodeblock %} 44 | 45 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2709.md: -------------------------------------------------------------------------------- 1 | ## TS2709 2 | 3 | > error TS2709: Cannot use namespace '`globalThis`' as a type. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function parseNumber(this: globalThis, input: string): number { 9 | return this.parseInt(input); 10 | } 11 | 12 | parseNumber.call(this, '100'); 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | You cannot use a namespace as a type, but you can get the type assigned with that namespace by using the `typeof` operator: 18 | 19 | ```ts 20 | function parseNumber(this: typeof globalThis, input: string): number { 21 | return this.parseInt(input); 22 | } 23 | 24 | parseNumber.call(this, '100'); 25 | ``` 26 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2713.md: -------------------------------------------------------------------------------- 1 | ## TS2713 2 | 3 | > error TS2713: Cannot access '`CheckSuite.status`' because '`CheckSuite`' is a type, but not a namespace. Did you mean to retrieve the type of the property '`status`' in '`CheckSuite`' with '`CheckSuite["status"]`'? 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock mark:7 %} 9 | type CheckSuite = { 10 | passed: boolean 11 | status: 'ok' | 'error' 12 | } 13 | 14 | type ServerResponse = { 15 | status: CheckSuite.status 16 | } 17 | {% endcodeblock %} 18 | 19 | 20 | ### Fixed Code ✔️ 21 | 22 | The utility type `Pick` comes in handy when you want to select and extract specific properties from one type and apply them to another type: 23 | 24 | 25 | {% codeblock mark:7 %} 26 | type CheckSuite = { 27 | passed: boolean 28 | status: 'ok' | 'error' 29 | } 30 | 31 | type ServerResponse = { 32 | status: Pick 33 | } 34 | {% endcodeblock %} 35 | 36 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2715.md: -------------------------------------------------------------------------------- 1 | ## TS2715 2 | 3 | > error TS2715: Abstract property 'name' in class 'Animal' cannot be accessed in the constructor. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | abstract class Animal { 9 | abstract name: string; 10 | } 11 | 12 | class Dog extends Animal { 13 | constructor(name: string) { 14 | super(); 15 | this.name = name; 16 | } 17 | } 18 | ``` 19 | 20 | ### Fixed Code ✔️ 21 | 22 | The `name` member of the abstract `Animal` class is `abstract`, so we have to define it ourselves in the derived class `Dog`. Because `name` has no access modifier, it is `public` by default which means that our `Dog` class has to implement it with a `public` visibility: 23 | 24 | ```ts 25 | abstract class Animal { 26 | abstract name: string; 27 | } 28 | 29 | class Dog extends Animal { 30 | public name; 31 | 32 | constructor(name: string) { 33 | super(); 34 | this.name = name; 35 | } 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2717.md: -------------------------------------------------------------------------------- 1 | ## TS2717 2 | 3 | > error TS2717: Subsequent property declarations must have the same type. Property '`verbose`' must be of type '`boolean`', but here has type '`string`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | declare namespace GreetingLib { 9 | interface LogOptions { 10 | verbose: boolean; 11 | } 12 | } 13 | 14 | declare namespace GreetingLib { 15 | interface LogOptions { 16 | verbose: string; 17 | } 18 | } 19 | ``` 20 | 21 | ### Fixed Code ✔️ 22 | 23 | When declaring a property (in this case `verbose`) twice, then the second declaration must follow the typings of the first declaration: 24 | 25 | ```ts 26 | declare namespace GreetingLib { 27 | interface LogOptions { 28 | verbose: boolean; 29 | } 30 | } 31 | 32 | declare namespace GreetingLib { 33 | interface LogOptions { 34 | verbose: boolean; 35 | } 36 | } 37 | ``` 38 | 39 | Usually the error TS2717 shows up when you have multiple versions of typings (i.e. `@types/react`) for the same interfaces in your codebase. If you run into these kind of problems, you can inspect your typing resolutions using `yarn why` (i.e. `yarn why @types/react`) or `npm explain` (i.e. `npm explain @types/react`) to find out where you have conflicting typings. 40 | 41 | ### Video Tutorial 42 | 43 | {% youtube eeXDwuAjSFo 'video' false %} 44 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2720.md: -------------------------------------------------------------------------------- 1 | ## TS2720 2 | 3 | > error TS2720: Class '`Dog`' incorrectly implements class '`Animal`'. Did you mean to extend '`Animal`' and inherit its members as a subclass? Property '`makeNoise`' is protected but type '`Dog`' is not a class derived from '`Animal`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | abstract class Animal { 9 | protected abstract makeNoise(): string; 10 | } 11 | 12 | class Dog implements Animal { 13 | protected makeNoise(): string { 14 | return 'Woof!'; 15 | } 16 | } 17 | ``` 18 | 19 | ### Fixed Code ✔️ 20 | 21 | The `implements` keyword is reserved to implement interfaces. If you want to work with class inheritance, you have to use `extends`: 22 | 23 | ```ts 24 | abstract class Animal { 25 | protected abstract makeNoise(): string; 26 | } 27 | 28 | class Dog extends Animal { 29 | protected makeNoise(): string { 30 | return 'Woof!'; 31 | } 32 | } 33 | ``` 34 | 35 | ### Video Tutorial 36 | 37 | {% youtube 62J_eQsK0e0?start=591 'video' false %} 38 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2722.md: -------------------------------------------------------------------------------- 1 | ## TS2722 2 | 3 | > error TS2722: Cannot invoke an object which is possibly '`undefined`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts mark:4 %} 9 | function handleClick(event: { 10 | onClick?: () => {} 11 | }): void { 12 | event.onClick(); 13 | } 14 | {% endcodeblock %} 15 | 16 | 17 | ### Fixed Code ✔️ 18 | 19 | Method invocation only works if the method is defined. The `onClick` method of the `event` object in the example above is optional, which means it can be `undefined`. That's why we have to make an existence check before calling / invoking it: 20 | 21 | 22 | {% codeblock lang:ts mark:4-6 %} 23 | function handleClick(event: { 24 | onClick?: () => {} 25 | }): void { 26 | if (event.onClick) { 27 | event.onClick(); 28 | } 29 | } 30 | {% endcodeblock %} 31 | 32 | 33 | As of TypeScript 3.7 you can also use the **optional chaining** (`?.`) operator to call a method on an object if it exists: 34 | 35 | 36 | {% codeblock lang:ts mark:4 %} 37 | function handleClick(event: { 38 | onClick?: () => {} 39 | }): void { 40 | event.onClick?.(); 41 | } 42 | {% endcodeblock %} 43 | 44 | 45 | A third possibility is to use reference validation: 46 | 47 | 48 | {% codeblock lang:ts mark:4 %} 49 | function handleClick(event: { 50 | onClick?: () => {} 51 | }): void { 52 | event.onClick && event.onClick(); 53 | } 54 | {% endcodeblock %} 55 | 56 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2724.md: -------------------------------------------------------------------------------- 1 | ## TS2724 2 | 3 | > error TS2724: '`./index`' has no exported member named '`HeaderOptions`'. Did you mean '`HeaderOption`'? 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts index.ts %} 9 | export interface HeaderOption { 10 | Authorization: string; 11 | 'Cache-Control': string; 12 | } 13 | {% endcodeblock %} 14 | 15 | 16 | 17 | {% codeblock lang:ts printHeader.ts %} 18 | import {HeaderOptions} from './index'; 19 | 20 | export function printHeader(header: HeaderOptions) { 21 | console.log(header); 22 | } 23 | {% endcodeblock %} 24 | 25 | 26 | ### Fixed Code ✔️ 27 | 28 | TypeScript noticed a typing error in the name of the imported interface. The code will work if we correct the typo: 29 | 30 | 31 | {% codeblock lang:ts printHeader.ts mark:1,3 %} 32 | import {HeaderOption} from './index'; 33 | 34 | export function printHeader(header: HeaderOption) { 35 | console.log(header); 36 | } 37 | {% endcodeblock %} 38 | 39 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2730.md: -------------------------------------------------------------------------------- 1 | ## TS2730 2 | 3 | > error TS2730: An arrow function cannot have a 'this' parameter. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const loadInitialData = (this: Highcharts.Chart): void => { 9 | // ... 10 | }; 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | You have to turn the **arrow function expression** into to a **function declaration**: 16 | 17 | ```ts 18 | function loadInitialData(this: Highcharts.Chart): void { 19 | // ... 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2732.md: -------------------------------------------------------------------------------- 1 | ## TS2732 2 | 3 | > error TS2732: Cannot find module '../../package.json'. Consider using '--resolveJsonModule' to import module with '.json' extension. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import pkg from '../../package.json'; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | To fix the issue and allow importing JSON files, you have to set "resolveJsonModule" to `true` in your "tsconfig.json" file. 14 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2739.md: -------------------------------------------------------------------------------- 1 | ## TS2739 2 | 3 | > error TS2739: Type '`{}`' is missing the following properties from type '`Person`': `age`, `name` 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type Person = { 9 | age: number; 10 | name: string; 11 | }; 12 | 13 | const benny: Person = {}; 14 | ``` 15 | 16 | ### Fixed Code ✔️ 17 | 18 | The object doesn't have any properties, so it cannot be assigned to the type of `Person`. We have to add the missing properties to fix this error: 19 | 20 | ```ts 21 | type Person = { 22 | age: number; 23 | name: string; 24 | }; 25 | 26 | const benny: Person = { 27 | age: 34, 28 | name: 'Benny', 29 | }; 30 | ``` 31 | 32 | ### Video Tutorial 33 | 34 | {% youtube 62J_eQsK0e0?start=1155 'video' false %} 35 | 36 | > TS2739: Type 'string[]' is missing the following properties from type 'Promise ': then, catch, [Symbol.toStringTag] 37 | 38 | ### Broken Code ❌ 39 | 40 | ```ts 41 | function myTest(): Promise { 42 | return ['']; 43 | } 44 | ``` 45 | 46 | When your function specifies to return a Promise, you have to ensure that your return value is also wrapped in a `Promise`: 47 | 48 | ```ts 49 | function myTest(): Promise { 50 | return Promise.resolve(['']); 51 | } 52 | ``` 53 | 54 | Alternatively, you can make use of the `async` keyword, which will automatically wrap your return value into a `Promise`: 55 | 56 | ```ts 57 | async function myTest(): Promise { 58 | return ['']; 59 | } 60 | ``` 61 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2740.md: -------------------------------------------------------------------------------- 1 | ## TS2740 2 | 3 | > error TS2740: Type '`TextLine`' is missing the following properties from type '`Position`': line, character, isBefore, isBeforeOrEqual, and 6 more. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import {Position, TextEditor} from 'vscode'; 9 | 10 | function logPosition(textEditor: TextEditor, startLine: Position = textEditor.document.lineAt(0)) { 11 | console.log(startLine.line); 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | The parameter `startLine` is requiring a value of type `Position` but the default value returns a value of type `TextLine`, so this has to be fixed to return the expected type: 18 | 19 | ```ts 20 | import {Position, TextEditor} from 'vscode'; 21 | 22 | function logPosition(textEditor: TextEditor, startLine: Position = textEditor.document.lineAt(0).range.start) { 23 | console.log(startLine.line); 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2741.md: -------------------------------------------------------------------------------- 1 | ## TS2741 2 | 3 | > error TS2741: Property 'name' is missing in type '{}' but required in type 'Animal'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | interface Animal { 9 | name: string; 10 | } 11 | 12 | const laika: Animal = {}; 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | Interfaces can be used with classes or plain objects. If we want our object (i.e. `laika`) to fulfill the contract of `Animal`, we have to assign all required properties to it: 18 | 19 | ```ts 20 | interface Animal { 21 | name: string; 22 | } 23 | 24 | const laika: Animal = { 25 | name: 'Laika', 26 | }; 27 | ``` 28 | 29 | ### Video Tutorial 30 | 31 | {% youtube 62J_eQsK0e0?start=1155 'video' false %} 32 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2749.md: -------------------------------------------------------------------------------- 1 | ## TS2749 2 | 3 | > error TS2749: '`paramNames`' refers to a value, but is being used as a type here. Did you mean '`typeof paramNames`'? 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const paramNames = ['age', 'name']; 9 | 10 | const person: { 11 | [param in paramNames]: string; 12 | } = { 13 | age: '34', 14 | name: 'Benny', 15 | }; 16 | ``` 17 | 18 | ### Fixed Code ✔️ 19 | 20 | ```ts 21 | type paramNames = 'age' | 'name'; 22 | 23 | const person: { 24 | [param in paramNames]: string; 25 | } = { 26 | age: '34', 27 | name: 'Benny', 28 | }; 29 | ``` 30 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2769.md: -------------------------------------------------------------------------------- 1 | ## TS2769 2 | 3 | > error TS2769: No overload matches this call. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function sum(a: number, b: number): number; 9 | function sum(a: string, b: string): string; 10 | function sum(a: number | string, b: number | string): number | string { 11 | if (typeof a === 'number' && typeof b === 'number') { 12 | return a + b; 13 | } 14 | return `${parseInt(a + '', 10) + parseInt(b + '', 10)}`; 15 | } 16 | 17 | const result = sum('1000', 337); 18 | ``` 19 | 20 | ### Fixed Code ✔️ 21 | 22 | There are only two **function overloads** for `sum`. The first overload expects `a` and `b` to be of type `number`. The second overload expects `a` and `b` to be of type `string` but there is no overload that specifies `a` to be a `string` while `b` is a `number`. We have to add a third overload to allow such function calls: 23 | 24 | ```ts 25 | // Function Overload Signature 1 26 | function sum(a: number, b: number): number; 27 | // Function Overload Signature 2 28 | function sum(a: string, b: string): string; 29 | // Function Overload Signature 3 30 | function sum(a: string, b: number): string; 31 | function sum(a: number | string, b: number | string): number | string { 32 | if (typeof a === 'number' && typeof b === 'number') { 33 | return a + b; 34 | } 35 | return `${parseInt(a + '', 10) + parseInt(b + '', 10)}`; 36 | } 37 | 38 | const result = sum('1000', 337); 39 | ``` 40 | 41 | An even easier solution would be to remove all function overloads as the function body allows us to use `number` or `string` through the [**union type**](/glossary/index.html#Union-Types) of `number | string`: 42 | 43 | ```ts 44 | function sum(a: number | string, b: number | string): number | string { 45 | if (typeof a === 'number' && typeof b === 'number') { 46 | return a + b; 47 | } 48 | return `${parseInt(a + '', 10) + parseInt(b + '', 10)}`; 49 | } 50 | 51 | const result = sum('1000', 337); 52 | ``` 53 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2774.md: -------------------------------------------------------------------------------- 1 | ## TS2774 2 | 3 | > error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | interface MyDog { 9 | age: () => number; 10 | } 11 | 12 | interface MyPerson { 13 | name: string; 14 | age: () => number; 15 | } 16 | 17 | function printAge(user: MyPerson | MyDog): void { 18 | if (user.age) { 19 | } 20 | } 21 | ``` 22 | 23 | ### Fixed Code ✔️ 24 | 25 | Both interfaces (`MyPerson` & `MyDog`) declare a function named `age`, so that `if`-condition to check for its existence is unnecessary: 26 | 27 | ```ts 28 | interface MyDog { 29 | age: () => number; 30 | } 31 | 32 | interface MyPerson { 33 | name: string; 34 | age: () => number; 35 | } 36 | 37 | function printAge(user: MyPerson | MyDog): void { 38 | console.log(user.age()); 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2779.md: -------------------------------------------------------------------------------- 1 | ## TS2779 2 | 3 | > error TS2779: The left-hand side of an assignment expression may not be an optional property access. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type User = { 9 | id: number; 10 | name: string; 11 | }; 12 | const someUsers: Map = new Map(); 13 | someUsers.get('some-user-id')?.name = 'Benny'; 14 | ``` 15 | 16 | ### Fixed Code ✔️ 17 | 18 | You cannot assign a value to a property which might be `undefined`. As [Map.get()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get) may return `undefined`, you have to add an existence check: 19 | 20 | 21 | {% codeblock lang:ts mark:7,9 %} 22 | type User = { 23 | id: number; 24 | name: string; 25 | } 26 | const someUsers: Map = new Map(); 27 | const user = someUsers.get('some-user-id'); 28 | if (user) { 29 | user.name = 'Benny'; 30 | } 31 | {% endcodeblock %} 32 | 33 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2786.md: -------------------------------------------------------------------------------- 1 | ## TS2786 2 | 3 | > error TS2786: '`Component`' cannot be used as a JSX component. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```tsx 8 | import type {NextPage} from 'next'; 9 | import type {AppProps} from 'next/app'; 10 | 11 | type AppPropsWithLayout = AppProps & { 12 | Component: NextPage & { 13 | getLayout?: (page: React.ReactElement) => React.ReactNode; 14 | }; 15 | }; 16 | 17 | export default function AdvisoryApp({Component, pageProps}: AppPropsWithLayout): JSX.Element { 18 | const getLayout = Component.getLayout ?? (page => page); 19 | return <>{getLayout()}; 20 | } 21 | ``` 22 | 23 | ### Fixed Code ✔️ 24 | 25 | Usually the problem derives from a mismatch in `@types/react`. When you have libraries that are dependent on a specific version of `@types/react` (i.e. v17.0.47) and you have other libraries working with another major version of `@types/react` (i.e. v18.0.14), then this can cause compatibility issues when using `React.ReactNode` or `JSX.Element`. You have to streamline your dependencies on `@types/react`, so that these follow the same major version. 26 | 27 | You can find all libraries depending on `@types/react` in your project by executing `npm explain @types/react` (when a `package-lock.json` file is present) or `yarn why @types/react` (when a `yarn.lock` file is present). 28 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2790.md: -------------------------------------------------------------------------------- 1 | ## TS2790 2 | 3 | > error TS2790: The operand of a 'delete' operator must be optional. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts mark:11 %} 9 | interface User { 10 | age: number; 11 | name: string; 12 | } 13 | 14 | const benny: User = { 15 | age: 35, 16 | name: 'Benny' 17 | }; 18 | 19 | delete benny.age; 20 | {% endcodeblock %} 21 | 22 | 23 | ### Fixed Code ✔️ 24 | 25 | When using the `delete` operator to remove a property from an object, the property must be defined as optional in TypeScript: 26 | 27 | 28 | {% codeblock lang:ts mark:2 %} 29 | interface User { 30 | age?: number; 31 | name: string; 32 | } 33 | 34 | const benny: User = { 35 | age: 35, 36 | name: 'Benny' 37 | }; 38 | 39 | delete benny.age; 40 | {% endcodeblock %} 41 | 42 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2792.md: -------------------------------------------------------------------------------- 1 | ## TS2792 2 | 3 | > error TS2792: Cannot find module '`@playwright/test`'. Did you mean to set the '`moduleResolution`' option to '`node`', or to add aliases to the '`paths`' option? 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock playwright.config.staging.ts lang:ts %} 9 | import { PlaywrightTestConfig } from '@playwright/test'; 10 | 11 | const config: PlaywrightTestConfig = { 12 | use: { 13 | baseURL: 'https://my-staging-environment.com/', 14 | }, 15 | }; 16 | 17 | export default config; 18 | {% endcodeblock %} 19 | 20 | 21 | 22 | {% codeblock lang:json tsconfig.json %} 23 | { 24 | "compilerOptions": { 25 | "moduleResolution": "classic" 26 | } 27 | } 28 | {% endcodeblock %} 29 | 30 | 31 | ### Fixed Code ✔️ 32 | 33 | To fix the problem you have to use `"moduleResolution": "node"` in your TS config: 34 | 35 | 36 | {% codeblock lang:json tsconfig.json %} 37 | { 38 | "compilerOptions": { 39 | "moduleResolution": "node" 40 | } 41 | } 42 | {% endcodeblock %} 43 | 44 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2794.md: -------------------------------------------------------------------------------- 1 | ## TS2794 2 | 3 | > error TS2794: Expected 1 arguments, but got 0. Did you forget to include '`void`' in your type argument to '`Promise`'? 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | await new Promise((resolve, reject) => { 9 | resolve(); 10 | }); 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | When a Promise resolves with nothing, you need to define that as a [**type argument**](/glossary/index.html#Type-Argument) to the generic `Promise`: 16 | 17 | ```ts 18 | await new Promise((resolve, reject) => { 19 | resolve(); 20 | }); 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2813.md: -------------------------------------------------------------------------------- 1 | ## TS2813 2 | 3 | > error TS2813: Class declaration cannot implement overload list for 'MyClass'. 4 | 5 | ### Solution 6 | 7 | ### Broken Code ❌ 8 | 9 | ```ts 10 | class MyClass {} 11 | 12 | function MyClass(): void {} 13 | ``` 14 | 15 | Function declarations get hoisted, so you cannot give your `class` the name of your function. Renaming your class solves the issue: 16 | 17 | ### Fixed Code ✔️ 18 | 19 | ```ts 20 | class MyClassWithAnotherName {} 21 | 22 | function MyClass(): void {} 23 | ``` 24 | -------------------------------------------------------------------------------- /errors/includes/TS2xxx/TS2814.md: -------------------------------------------------------------------------------- 1 | ## TS2814 2 | 3 | > error TS2814: Function with bodies can only merge with classes that are ambient. 4 | 5 | ### Solution 6 | 7 | ### Broken Code ❌ 8 | 9 | ```ts 10 | class MyClass {} 11 | 12 | function MyClass(): void {} 13 | ``` 14 | 15 | Your `function` cannot be named after your `class`, so you will have to rename your function: 16 | 17 | ### Fixed Code ✔️ 18 | 19 | ```ts 20 | class MyClass {} 21 | 22 | function MyFunctionWithAnotherName(): void {} 23 | ``` 24 | 25 | Alternatively you can declare an ambient class which gets implemented by your function: 26 | 27 | ```ts 28 | declare class MyClass {} 29 | 30 | function MyClass(): void {} 31 | ``` 32 | -------------------------------------------------------------------------------- /errors/includes/TS4xxx/TS4020.md: -------------------------------------------------------------------------------- 1 | ## TS4020 2 | 3 | > error TS4020: 'extends' clause of exported class '`StrategyPOJO`' has or is using private name '`Model`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const {Model} = require('objection'); 9 | 10 | class StrategyPOJO extends Model { 11 | static tableName = 'strategies'; 12 | config: string | undefined; 13 | exchange: string | undefined; 14 | identifier: string | undefined; 15 | symbol: string | undefined; 16 | } 17 | 18 | export {StrategyPOJO}; 19 | ``` 20 | 21 | ### Fixed Code ✔️ 22 | 23 | ```ts 24 | import {Model} from 'objection'; 25 | 26 | class StrategyPOJO extends Model { 27 | static tableName = 'strategies'; 28 | config: string | undefined; 29 | exchange: string | undefined; 30 | identifier: string | undefined; 31 | symbol: string | undefined; 32 | } 33 | 34 | export {StrategyPOJO}; 35 | ``` 36 | -------------------------------------------------------------------------------- /errors/includes/TS4xxx/TS4025.md: -------------------------------------------------------------------------------- 1 | ## TS4025 2 | 3 | > error TS4025: Exported variable '`App`' has or is using private name '`FC`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```tsx 8 | import React from 'react'; 9 | 10 | const App: FC = (): JSX.Element => { 11 | return <>; 12 | }; 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | When using an external type (like `FC`) you also have to make sure that it is imported: 18 | 19 | ```tsx 20 | import React, {FC} from 'react'; 21 | 22 | const App: FC = (): JSX.Element => { 23 | return <>; 24 | }; 25 | ``` 26 | -------------------------------------------------------------------------------- /errors/includes/TS4xxx/TS4060.md: -------------------------------------------------------------------------------- 1 | ## TS4060 2 | 3 | > error TS4060: Return type of exported function has or is using private name 'JSX'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```tsx 8 | function App(): JSX.Element { 9 | return

My App!

; 10 | } 11 | 12 | export default App; 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | The global JSX namespace is declared in `@types/react`. You have to install the `@types/react` package to make use of it: 18 | 19 | ```bash 20 | yarn add --dev @types/react 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS4xxx/TS4063.md: -------------------------------------------------------------------------------- 1 | ## TS4063 2 | 3 | > error TS4063: Parameter '`config`' of constructor from exported class has or is using private name '`DoubleMovingAverageConfig`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | type DoubleMovingAverageConfig = { 9 | lastBuyPrice: string; 10 | lastSellPrice: string; 11 | warmUpCandles: number; 12 | }; 13 | 14 | class DoubleMovingAverage extends Strategy { 15 | constructor(private setup: StrategySetup, private config?: DoubleMovingAverageConfig) {} 16 | } 17 | ``` 18 | 19 | ### Fixed Code ✔️ 20 | 21 | ```ts 22 | export type DoubleMovingAverageConfig = { 23 | lastBuyPrice: string; 24 | lastSellPrice: string; 25 | warmUpCandles: number; 26 | }; 27 | 28 | class DoubleMovingAverage extends Strategy { 29 | constructor(private setup: StrategySetup, private config?: DoubleMovingAverageConfig) {} 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /errors/includes/TS4xxx/TS4075.md: -------------------------------------------------------------------------------- 1 | ## TS4075 2 | 3 | > error TS4075: Parameter 'event' of method from exported interface has or is using private name 'Strategy'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export interface Strategy { 9 | on(event: Strategy.TOPIC.TRADER_DELETE, listener: () => void): this; 10 | } 11 | 12 | export abstract class Strategy extends EventEmitter { 13 | static readonly TOPIC = { 14 | TRADER_DELETE: 'TRADER_DELETE', 15 | }; 16 | 17 | // ... 18 | } 19 | ``` 20 | 21 | ### Fixed Code ✔️ 22 | 23 | ```ts 24 | enum TOPIC { 25 | TRADER_DELETE = 'TRADER_DELETE', 26 | } 27 | 28 | export interface Strategy { 29 | on(event: TOPIC.TRADER_DELETE, listener: () => void): this; 30 | } 31 | 32 | export abstract class Strategy extends EventEmitter { 33 | static readonly TOPIC = TOPIC; 34 | 35 | // ... 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /errors/includes/TS4xxx/TS4081.md: -------------------------------------------------------------------------------- 1 | ## TS4081 2 | 3 | > error TS4081: Exported type alias '`MyReturnType`' has or is using private name '`getSdk`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts index.ts %} 9 | export type MyReturnType = ReturnType; 10 | {% endcodeblock %} 11 | 12 | 13 | 14 | {% codeblock lang:ts getSdk.ts %} 15 | function getSdk() {} 16 | {% endcodeblock %} 17 | 18 | 19 | ### Fixed Code ✔️ 20 | 21 | The `getSdk` is identified to be private because it is not exported. If we export the `getSdk` function, we won't have any more problems: 22 | 23 | 24 | {% codeblock lang:ts index.ts mark:1 %} 25 | import {getSdk} from './getSdk'; 26 | 27 | export type MyReturnType = ReturnType; 28 | {% endcodeblock %} 29 | 30 | 31 | 32 | {% codeblock lang:ts getSdk.ts mark:1 %} 33 | export function getSdk() {} 34 | {% endcodeblock %} 35 | 36 | -------------------------------------------------------------------------------- /errors/includes/TS4xxx/TS4104.md: -------------------------------------------------------------------------------- 1 | ## TS4104 2 | 3 | > error TS4104: The type '`readonly [1, 2, 3]`' is 'readonly' and cannot be assigned to the mutable type '`[1, 2, 3]`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const array: [1, 2, 3] = [1, 2, 3] as const; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | Using a **const assertion** makes your array immutable, so you have to use the `readonly` modifier for its type: 14 | 15 | ```ts 16 | const array: readonly [1, 2, 3] = [1, 2, 3] as const; 17 | ``` 18 | 19 | Alternative: 20 | 21 | ```ts 22 | const array: Readonly<[1, 2, 3]> = [1, 2, 3] as const; 23 | ``` 24 | 25 | Alternative #2: 26 | 27 | ```ts 28 | const array: ReadonlyArray = [1, 2, 3] as const; 29 | ``` 30 | -------------------------------------------------------------------------------- /errors/includes/TS4xxx/TS4112.md: -------------------------------------------------------------------------------- 1 | ## TS4112 2 | 3 | > error TS4112: This member cannot have an 'override' modifier because its containing class does not extend another class. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | class Cat { 9 | override makeNoise(): string { 10 | return 'Meow!'; 11 | } 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | ```ts 18 | class Cat { 19 | makeNoise(): string { 20 | return 'Meow!'; 21 | } 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /errors/includes/TS4xxx/TS4113.md: -------------------------------------------------------------------------------- 1 | ## TS4113 2 | 3 | > error TS4113: This member cannot have an '`override`' modifier because it is not declared in the base class '`MyBaseClass`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | class MyBaseClass { 9 | sayHello(): string { 10 | return 'Hello!'; 11 | } 12 | } 13 | 14 | class MyDerivedClass extends MyBaseClass { 15 | override sayWelcome(): string { 16 | return 'Welcome!'; 17 | } 18 | } 19 | ``` 20 | 21 | ### Fixed Code ✔️ 22 | 23 | You can only override functions in our derived class when those exist in our base class. We can solve the error by overwriting an existing function: 24 | 25 | ```ts 26 | class MyBaseClass { 27 | sayHello(): string { 28 | return 'Hello!'; 29 | } 30 | } 31 | 32 | class MyDerivedClass extends MyBaseClass { 33 | override sayHello(): string { 34 | return 'Welcome!'; 35 | } 36 | } 37 | ``` 38 | 39 | Depending on our use case, we can also remove the `override` modifier: 40 | 41 | ```ts 42 | class MyBaseClass { 43 | sayHello(): string { 44 | return 'Hello!'; 45 | } 46 | } 47 | 48 | class MyDerivedClass extends MyBaseClass { 49 | sayWelcome(): string { 50 | return 'Welcome!'; 51 | } 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /errors/includes/TS4xxx/TS4114.md: -------------------------------------------------------------------------------- 1 | ## TS4114 2 | 3 | > error TS4114: This member must have an '`override`' modifier because it overrides a member in the base class '`MyBaseClass`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | class MyBaseClass { 9 | sayHello(): string { 10 | return 'Hello!'; 11 | } 12 | } 13 | 14 | class MyDerivedClass extends MyBaseClass { 15 | sayHello(): string { 16 | return 'Welcome!'; 17 | } 18 | } 19 | ``` 20 | 21 | ### Fixed Code ✔️ 22 | 23 | The error pops up when "noImplicitOverride" is set to `true` in your "tsconfig.json" file, and you don't use the `override` modifier when overwriting a function from your base class. You can fix this by setting "noImplicitOverride" to `false` (not recommended) or using the `override` modifier (preferred solution): 24 | 25 | ```ts 26 | class MyBaseClass { 27 | sayHello(): string { 28 | return 'Hello!'; 29 | } 30 | } 31 | 32 | class MyDerivedClass extends MyBaseClass { 33 | override sayHello(): string { 34 | return 'Welcome!'; 35 | } 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /errors/includes/TS5xxx/TS5023.md: -------------------------------------------------------------------------------- 1 | ## TS5023 2 | 3 | > error TS5023: Unknown compiler option '`-c`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```bash 8 | npx tsc -c mytsconfig.json 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | If you want to point the TypeScript compiler to a different configuration, you have to use the `--project` flag (see all [tsc CLI options](https://www.typescriptlang.org/docs/handbook/compiler-options.html)): 14 | 15 | ```bash 16 | npx tsc --project mytsconfig.json 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS5xxx/TS5024.md: -------------------------------------------------------------------------------- 1 | ## TS5024 2 | 3 | > error TS5024: Compiler option 'lib' requires a value of type string. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```json 8 | { 9 | "compilerOptions": { 10 | "lib": [6], 11 | "module": "commonjs", 12 | "moduleResolution": "node", 13 | "outDir": "dist", 14 | "rootDir": "src", 15 | "target": "es6" 16 | } 17 | } 18 | ``` 19 | 20 | ### Fixed Code ✔️ 21 | 22 | You have to define a valid set of high level libraries (such as "es6") that are available in your runtime: 23 | 24 | ```json 25 | { 26 | "compilerOptions": { 27 | "lib": ["es6"], 28 | "module": "commonjs", 29 | "moduleResolution": "node", 30 | "outDir": "dist", 31 | "rootDir": "src", 32 | "target": "es6" 33 | } 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /errors/includes/TS5xxx/TS5025.md: -------------------------------------------------------------------------------- 1 | ## TS5025 2 | 3 | > error TS5025: Unknown compiler option '--no-emit'. Did you mean 'noEmit'? 4 | 5 | ### Broken Code ❌ 6 | 7 | ```bash 8 | tsc --no-emit 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | Use camel case writing: 14 | 15 | ```bash 16 | tsc --noEmit 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS5xxx/TS5042.md: -------------------------------------------------------------------------------- 1 | ## TS5042 2 | 3 | > error TS5042: Option 'project' cannot be mixed with source files on a command line. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```bash 8 | npx tsc -p tsconfig.strict.json src/main.ts 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | If you're using the `-p` / `--project` option, it's not possible to directly pass a source file as an argument to the TypeScript compiler. If you want to specify the files to be compiled while using the project option from the command line interface (CLI), you need to add the desired files to the `include` section of your TypeScript project configuration: 14 | 15 | 16 | {% codeblock lang:json tsconfig.strict.json mark:7 %} 17 | { 18 | "$schema": "https://json.schemastore.org/tsconfig", 19 | "compilerOptions": { 20 | "outDir": "dist" 21 | }, 22 | "extends": "@tstv/tsconfig-common/tsconfig.json", 23 | "include": ["src/main.ts"] 24 | } 25 | {% endcodeblock %} 26 | 27 | -------------------------------------------------------------------------------- /errors/includes/TS5xxx/TS5054.md: -------------------------------------------------------------------------------- 1 | ## TS5054 2 | 3 | > error TS5054: A 'tsconfig.json' file is already defined at: '`C:/dev/bennycode/ts-node-starter/tsconfig.json`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```bash 8 | npx tsc --init 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | You cannot initialize a new TypeScript compiler configuration when there is one already present. You have to delete the existing file first. 14 | -------------------------------------------------------------------------------- /errors/includes/TS5xxx/TS5055.md: -------------------------------------------------------------------------------- 1 | ## TS5055 2 | 3 | > error TS5055: Cannot write file because it would overwrite input file. Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```bash 8 | tsc mycode.js --allowJs 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | ```bash 14 | tsc mycode.js --allowJs --outDir dist 15 | ``` 16 | 17 | Alternatively, you can also skip compiling code (if you just want to check the types of your code): 18 | 19 | ```bash 20 | tsc mycode.js --allowJs --noEmit 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS5xxx/TS5058.md: -------------------------------------------------------------------------------- 1 | ## TS5058 2 | 3 | > error TS5058: The specified path does not exist: 'test.json'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```bash 8 | npx tsc --project test.json 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | You probably don't have a TS config named `test.json`. Try to load `tsconfig.json`: 14 | 15 | ```bash 16 | npx tsc --project tsconfig.json 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS5xxx/TS5069.md: -------------------------------------------------------------------------------- 1 | ## TS5069 2 | 3 | > error TS5069: Option 'declarationMap' cannot be specified without specifying option 'declaration' or option 'composite'. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:json tsconfig.json %} 9 | { 10 | "compilerOptions": { 11 | "declaration": false, 12 | "declarationMap": true 13 | } 14 | } 15 | {% endcodeblock %} 16 | 17 | 18 | ### Fixed Code ✔️ 19 | 20 | You have to activate the "declaration" property before you can activate "declarationMap": 21 | 22 | 23 | {% codeblock lang:json mark:3 tsconfig.json %} 24 | { 25 | "compilerOptions": { 26 | "declaration": true, 27 | "declarationMap": true 28 | } 29 | } 30 | {% endcodeblock %} 31 | 32 | -------------------------------------------------------------------------------- /errors/includes/TS5xxx/TS5070.md: -------------------------------------------------------------------------------- 1 | ## TS5070 2 | 3 | > error TS5070: Option '--resolveJsonModule' cannot be specified without 'node' module resolution strategy. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```json 8 | { 9 | "compilerOptions": { 10 | "jsx": "preserve", 11 | "lib": ["dom", "dom.iterable", "esnext"], 12 | "module": "esnext", 13 | "resolveJsonModule": true, 14 | "target": "es6" 15 | } 16 | } 17 | ``` 18 | 19 | ### Fixed Code ✔️ 20 | 21 | Just define the "moduleResolution" property and set it to "node": 22 | 23 | 24 | {% codeblock lang:json tsconfig.json mark:10 %} 25 | { 26 | "compilerOptions": { 27 | "jsx": "preserve", 28 | "lib": [ 29 | "dom", 30 | "dom.iterable", 31 | "esnext" 32 | ], 33 | "module": "esnext", 34 | "moduleResolution": "node", 35 | "resolveJsonModule": true, 36 | "target": "es6" 37 | } 38 | } 39 | {% endcodeblock %} 40 | 41 | -------------------------------------------------------------------------------- /errors/includes/TS5xxx/TS5083.md: -------------------------------------------------------------------------------- 1 | ## TS5083 2 | 3 | > error TS5083: Cannot read file '`base.json`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```json 8 | { 9 | "extends": "./base.json", 10 | "compilerOptions": { 11 | "lib": ["dom", "es6"], 12 | "module": "commonjs", 13 | "moduleResolution": "node", 14 | "outDir": "dist", 15 | "rootDir": "src", 16 | "target": "es6" 17 | } 18 | } 19 | ``` 20 | 21 | ### Fixed Code ✔️ 22 | 23 | Your TS config is extending another config (called `base.json`) which cannot be found. Make sure that this file (`base.json`) exists or remove your `extends` property. 24 | -------------------------------------------------------------------------------- /errors/includes/TS5xxx/TS5087.md: -------------------------------------------------------------------------------- 1 | ## TS5087 2 | 3 | > error TS5087: A labeled tuple element is declared as rest with a '`...`' before the name, rather than before the type. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```bash 8 | type Operation = "+" | "-"; 9 | 10 | type CalcInput = [operation: Operation, numbers: ...number[]]; 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | We have to move the rest operator to the label name: 16 | 17 | ```bash 18 | type CalcInput = [operation: Operation, ...numbers: number[]]; 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS5xxx/TS5101.md: -------------------------------------------------------------------------------- 1 | ## TS5101 2 | 3 | > error TS5101: Option 'importsNotUsedAsValues' is deprecated and will stop functioning in TypeScript 5.5. Specify compilerOption '"ignoreDeprecations": "5.0"' to silence this error. Use 'verbatimModuleSyntax' instead. 4 | 5 | 6 | {% codeblock lang:json tsconfig.json %} 7 | { 8 | "compilerOptions": { 9 | "importsNotUsedAsValues": "error" 10 | } 11 | } 12 | {% endcodeblock %} 13 | 14 | 15 | ### Fixed Code ✔️ 16 | 17 | The compiler option [importsNotUsedAsValues](https://www.typescriptlang.org/tsconfig#importsNotUsedAsValues) is not recommended when using TypeScript 5 and above, so you have to remove it from your **tsconfig.json** file: 18 | 19 | 20 | {% codeblock lang:json tsconfig.json %} 21 | { 22 | "compilerOptions": { 23 | } 24 | } 25 | {% endcodeblock %} 26 | 27 | -------------------------------------------------------------------------------- /errors/includes/TS6xxx/TS6053.md: -------------------------------------------------------------------------------- 1 | ## TS6053 2 | 3 | > error TS6053: File '`/typings/index.d.ts`' not found. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | /// 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | Use relative paths when using [Triple-Slash Directives](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html): 14 | 15 | ```ts 16 | /// 17 | ``` 18 | 19 | Read more: [8 Steps to Migrating from JavaScript to TypeScript](https://www.webcodegeeks.com/javascript/8-steps-migrating-javascript-typescript/) 20 | -------------------------------------------------------------------------------- /errors/includes/TS6xxx/TS6059.md: -------------------------------------------------------------------------------- 1 | ## TS6059 2 | 3 | > error TS6059: File '`/root/project/packages/server/package.json`' is not under 'rootDir' '`/root/project/packages/server/src`'. 'rootDir' is expected to contain all source files. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | import pkg from '../../../../package.json'; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | When using `require` then we can access files outside the specified root folder for input files ("rootDir" in "tsconfig.json"): 14 | 15 | ```ts 16 | const pkg = require('../../../../package.json'); 17 | ``` 18 | 19 | An even better solution would be changing the "rootDir" in your "tsconfig.json", so that it includes the "package.json" file that you are trying to important. This may require you to also set "allowJs" to `true` in your "tsconfig.json". 20 | -------------------------------------------------------------------------------- /errors/includes/TS6xxx/TS6133.md: -------------------------------------------------------------------------------- 1 | ## TS6133 2 | 3 | > error TS6133: '`volume`' is declared but its value is never read. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts test.ts %} 9 | const closes = ohlc.map(([time, open, high, low, close, volume]) => (close)); 10 | {% endcodeblock %} 11 | 12 | 13 | 14 | {% codeblock lang:json tsconfig.json %} 15 | { 16 | "compilerOptions": { 17 | "noUnusedParameters": true 18 | } 19 | } 20 | {% endcodeblock %} 21 | 22 | 23 | ### Fixed Code ✔️ 24 | 25 | 26 | {% codeblock lang:json tsconfig.json mark:3 %} 27 | { 28 | "compilerOptions": { 29 | "noUnusedParameters": false 30 | } 31 | } 32 | {% endcodeblock %} 33 | 34 | 35 | > error TS6133: '`b`' is declared but its value is never read. 36 | 37 | 38 | {% codeblock lang:ts test.ts %} 39 | let b; 40 | {% endcodeblock %} 41 | 42 | 43 | 44 | {% codeblock lang:json tsconfig.json %} 45 | { 46 | "compilerOptions": { 47 | "noUnusedLocals": true 48 | } 49 | } 50 | {% endcodeblock %} 51 | 52 | 53 | ### Fixed Code ✔️ 54 | 55 | You can remove the unused variable from your code or disable the check for unused variables in your TypeScript compiler config: 56 | 57 | 58 | {% codeblock lang:json tsconfig.json mark:3 %} 59 | { 60 | "compilerOptions": { 61 | "noUnusedLocals": false 62 | } 63 | } 64 | {% endcodeblock %} 65 | 66 | 67 | ### Video Tutorial 68 | 69 | {% youtube 62J_eQsK0e0?start=78 'video' false %} 70 | -------------------------------------------------------------------------------- /errors/includes/TS6xxx/TS6138.md: -------------------------------------------------------------------------------- 1 | ## TS6138 2 | 3 | > error TS6138: Property '`lastName`' is declared but its value is never read. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock lang:ts User.ts %} 9 | class User { 10 | constructor(private firstName: string, private lastName: string) { 11 | } 12 | 13 | get fullName() { 14 | return this.firstName; 15 | } 16 | } 17 | {% endcodeblock %} 18 | 19 | 20 | ### Fixed Code ✔️ 21 | 22 | Simply make use of the `lastName` property: 23 | 24 | 25 | {% codeblock lang:ts User.ts mark:6 %} 26 | class User { 27 | constructor(private firstName: string, private lastName: string) { 28 | } 29 | 30 | get fullName() { 31 | return `${this.firstName} ${this.lastName}`; 32 | } 33 | } 34 | {% endcodeblock %} 35 | 36 | -------------------------------------------------------------------------------- /errors/includes/TS6xxx/TS6196.md: -------------------------------------------------------------------------------- 1 | ## TS6196 2 | 3 | > error TS6196: '`MyAbstractClass`' is declared but never used. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | abstract class MyAbstractClass { 9 | abstract getResult(): boolean; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | You have three possibilities to fix the broken code: 16 | 17 | 1. Make use of `MyAbstractClass` in your application 18 | 2. Export `MyAbstractClass` 19 | 3. Set "noUnusedLocals" to `false` in your "tsconfig.json" 20 | 21 | ```ts 22 | export abstract class MyAbstractClass { 23 | abstract getResult(): boolean; 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /errors/includes/TS6xxx/TS6198.md: -------------------------------------------------------------------------------- 1 | ## TS6198 2 | 3 | > error TS6198: All destructured elements are unused. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function returnSomething(): {low: number; high: number} { 9 | return { 10 | low: 10, 11 | high: 20, 12 | }; 13 | } 14 | 15 | const {low: lowest, high: highest} = returnSomething(); 16 | ``` 17 | 18 | ### Fixed Code ✔️ 19 | 20 | You have to make use of the destructured values in your application / code: 21 | 22 | ```ts 23 | function returnSomething(): {low: number; high: number} { 24 | return { 25 | low: 10, 26 | high: 20, 27 | }; 28 | } 29 | 30 | const {low: lowest, high: highest} = returnSomething(); 31 | 32 | console.log(lowest + highest); 33 | ``` 34 | -------------------------------------------------------------------------------- /errors/includes/TS6xxx/TS6504.md: -------------------------------------------------------------------------------- 1 | ## TS6504 2 | 3 | > error TS6504: File '`mycode.js`' is a JavaScript file. Did you mean to enable the '`allowJs`' option? 4 | 5 | ### Broken Code ❌ 6 | 7 | ```bash 8 | tsc mycode.js 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | You have to enable the "allowJS" flag in your "tsconfig.json" file: 14 | 15 | 16 | {% codeblock lang:json tsconfig.json mark:3 %} 17 | { 18 | "compilerOptions": { 19 | "allowJs": true 20 | } 21 | } 22 | {% endcodeblock %} 23 | 24 | 25 | Alternatively, you can enable it through the [TypeScript Compiler CLI](https://www.typescriptlang.org/docs/handbook/compiler-options.html): 26 | 27 | ```bash 28 | tsc mycode.js --allowJs 29 | ``` 30 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7006.md: -------------------------------------------------------------------------------- 1 | ## TS7006 2 | 3 | > error TS7006: Parameter '`person`' implicitly has an '`any`' type. 4 | 5 | ### Broken Code ❌ 6 | 7 | 8 | {% codeblock main.ts lang:ts %} 9 | function greeter(person) { 10 | return `Hello, ${person}`; 11 | } 12 | {% endcodeblock %} 13 | 14 | 15 | 16 | {% codeblock tsconfig.json lang:json %} 17 | { 18 | "compilerOptions": { 19 | "noImplicitAny": true 20 | } 21 | } 22 | {% endcodeblock %} 23 | 24 | 25 | ### Fixed Code ✔️ 26 | 27 | You have to define the type for the argument named `person`: 28 | 29 | 30 | {% codeblock main.ts lang:ts %} 31 | function greeter(person: string) { 32 | return `Hello, ${person}`; 33 | } 34 | {% endcodeblock %} 35 | 36 | 37 | Alternative, but not recommend: 38 | 39 | - Set "noImplicitAny" to `false` in your "tsconfig.json" 40 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7008.md: -------------------------------------------------------------------------------- 1 | ## TS7008 2 | 3 | > error TS7008: Member '`name`' implicitly has an 'any' type. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | abstract class Person { 9 | accessor name; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | To fix the problem, you can initialize the class member so that TypeScript can infer the type: 16 | 17 | ```ts 18 | abstract class Person { 19 | accessor name = 'unknown'; 20 | } 21 | ``` 22 | 23 | Alternatively, you can annotate the type: 24 | 25 | ```ts 26 | abstract class Person { 27 | accessor name: string; 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7009.md: -------------------------------------------------------------------------------- 1 | ## TS7009 2 | 3 | > error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export function getPromise(): Promise { 9 | return new Promise.resolve(); 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | The `resolve` function of a `Promise` is not a constructor. You can use the `new` keyword only with constructors, so the `new` keyword has to be removed in order to fix the code: 16 | 17 | ```ts 18 | export function getPromise(): Promise { 19 | return Promise.resolve(); 20 | } 21 | ``` 22 | 23 | Alternatively, you can make use of the constructor: 24 | 25 | ```ts 26 | export function getPromise(): Promise { 27 | return new Promise(resolve => { 28 | resolve(); 29 | }); 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7010.md: -------------------------------------------------------------------------------- 1 | ## TS7010 2 | 3 | > error TS7010: '`sum`', which lacks return-type annotation, implicitly has an '`any`' return type. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | namespace MyModule { 9 | export function sum(a: number, b: number); 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | You have to add a **return-type annotation** and preferably a **function implementation**: 16 | 17 | ```ts 18 | namespace MyModule { 19 | export function sum(a: number, b: number): number { 20 | return a + b; 21 | } 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7017.md: -------------------------------------------------------------------------------- 1 | ## TS7017 2 | 3 | > error TS7017: Element implicitly has an '`any`' type because type '`{}`' has no index signature. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const recipients = {}; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | You have to define the type for indexing your object properties (`object["index"]`): 14 | 15 | ```ts 16 | const recipients: {[index: string]: number} = {}; 17 | ``` 18 | 19 | The name of the index can be freely chosen: 20 | 21 | ```ts 22 | const recipients: {[myKey: string]: number} = {}; 23 | ``` 24 | 25 | How to fix such errors in interfaces: 26 | 27 | ```ts 28 | interface Recipients { 29 | [index: string]: number; 30 | } 31 | ``` 32 | 33 | Alternative, but not recommend: 34 | 35 | - Set "noImplicitAny" to `false` in your "tsconfig.json" 36 | 37 | > error TS7017: Element implicitly has an '`any`' type because type '`typeof globalThis`' has no index signature. 38 | 39 | ### Broken Code ❌ 40 | 41 | ```ts 42 | global.client = new APIClient(APIClient.URL_DEMO, 'global-demo-api-key'); 43 | ``` 44 | 45 | ### Fixed Code ✔️ 46 | 47 | ```ts 48 | declare global { 49 | var client: APIClient; 50 | } 51 | 52 | global.client = new APIClient(APIClient.URL_DEMO, 'global-demo-api-key'); 53 | ``` 54 | 55 | **Reference:** 56 | 57 | - https://github.com/microsoft/TypeScript/issues/30139#issuecomment-913018222 58 | 59 | ### Video Tutorial 60 | 61 | {% youtube XoOgNRQEYws?start=835 'video' false %} 62 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7022.md: -------------------------------------------------------------------------------- 1 | ## TS7022 2 | 3 | > error TS7022: '`window`' implicitly has type '`any`' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | var window = window || null; 9 | ``` 10 | 11 | 12 | {% codeblock lang:json tsconfig.json %} 13 | { 14 | "compilerOptions": { 15 | "lib": ["es2017"] 16 | } 17 | {% endcodeblock %} 18 | 19 | 20 | ### Fixed Code ✔️ 21 | 22 | The above error can occur when TypeScript doesn't know about the [window interface](https://developer.mozilla.org/en-US/docs/Web/API/Window). Make sure to add "dom" to your list of known runtime libraries in your compiler options: 23 | 24 | 25 | {% codeblock lang:json tsconfig.json %} 26 | { 27 | "compilerOptions": { 28 | "lib": ["dom", "es2017"] 29 | } 30 | {% endcodeblock %} 31 | 32 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7023.md: -------------------------------------------------------------------------------- 1 | ## TS7023 2 | 3 | > error TS7023: '`fibonacci`' implicitly has return type '`any`' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function fibonacci(n) { 9 | return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | To avoid the implicit typing of `any` for the return type, you have to add a **return type annotation**: 16 | 17 | ```ts 18 | function fibonacci(n): number { 19 | return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7026.md: -------------------------------------------------------------------------------- 1 | ## TS7026 2 | 3 | > error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```tsx 8 | function App() { 9 | return

My App!

; 10 | } 11 | 12 | export default App; 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | The global JSX namespace is declared in `@types/react`. You have to install the `@types/react` package to make use of it: 18 | 19 | ```bash 20 | yarn add --dev @types/react 21 | ``` 22 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7027.md: -------------------------------------------------------------------------------- 1 | ## TS7027 2 | 3 | > error TS7027: Unreachable code detected. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | process.exit(0); 9 | console.log('Hello, World!'); 10 | ``` 11 | 12 | ### Fixed Code ✔️ 13 | 14 | Your code cannot print text to the **standard output** when your program is told to exit beforehand, so you have to remove the call to exit or place it at a later point in time: 15 | 16 | ```ts 17 | console.log('Hello, World!'); 18 | process.exit(0); 19 | ``` 20 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7030.md: -------------------------------------------------------------------------------- 1 | ## TS7030 2 | 3 | > error TS7030: Not all code paths return a value. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function getFlightType(type: 1 | 2) { 9 | if (type === 1) { 10 | return 'Return trip'; 11 | } 12 | } 13 | ``` 14 | 15 | ### Fixed Code ✔️ 16 | 17 | TypeScript reminds us that we forgot to return a value in case our if-condition doesn't match. We can solve this problem in many ways. 18 | 19 | **Always return a value:** 20 | 21 | ```ts 22 | function getFlightType(type: 1 | 2) { 23 | if (type === 1) { 24 | return 'Return trip'; 25 | } 26 | return 'One way'; 27 | } 28 | ``` 29 | 30 | **Add general `else`:** 31 | 32 | ```ts 33 | function getFlightType(type: 1 | 2) { 34 | if (type === 1) { 35 | return 'Return trip'; 36 | } else { 37 | return 'One way'; 38 | } 39 | } 40 | ``` 41 | 42 | **Handle all `cases`:** 43 | 44 | ```ts 45 | function getFlightType(type: 1 | 2) { 46 | switch (type) { 47 | case 1: 48 | return 'Return trip'; 49 | case 2: 50 | return 'One way'; 51 | } 52 | } 53 | ``` 54 | 55 | **Add `default` case:** 56 | 57 | ```ts 58 | function getFlightType(type: 1 | 2) { 59 | switch (type) { 60 | case 1: 61 | return 'Return trip'; 62 | default: 63 | return 'One way'; 64 | } 65 | } 66 | ``` 67 | 68 | **Define that the return type can be `void`:** 69 | 70 | ```ts 71 | function getFlightType(type: 1 | 2): string | void { 72 | if (type === 1) { 73 | return 'Return trip'; 74 | } 75 | } 76 | ``` 77 | 78 | ### Video Tutorial 79 | 80 | {% youtube 8N_P-l5Kukk?start=352 'video' false %} 81 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7031.md: -------------------------------------------------------------------------------- 1 | ## TS7031 2 | 3 | > error TS7031: Binding element 'age' implicitly has an 'any' type. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | export function printAge({age}): void { 9 | console.log(age); 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | TypeScript complains because it doesn't know the type of the argument that we are destructuring. That's why it sets all its properties to the type of `any`. To prevent that we have to define a type for the parameter of the `printAge` function: 16 | 17 | ```ts 18 | type Person = { 19 | age: number; 20 | name: string; 21 | }; 22 | 23 | export function printAge({age}: Person): void { 24 | console.log(age); 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7034.md: -------------------------------------------------------------------------------- 1 | ## TS7034 2 | 3 | > error TS7034: Variable '`expectations`' implicitly has type '`any[]`' in some locations where its type cannot be determined. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const expectations = []; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | An array can collect values of different types, so we have to tell TypeScript which types we want to collect: 14 | 15 | ```ts 16 | const expectations: string[] = []; 17 | ``` 18 | 19 | If we want to specify multiple types, we have to define a [**union type**](/glossary/index.html#Union-Types): 20 | 21 | ```ts 22 | const expectations: (string | number)[] = []; 23 | expectations.push('1'); 24 | expectations.push(2); 25 | ``` 26 | 27 | Alternative: 28 | 29 | ```ts 30 | type ArrayInput = string | number; 31 | const expectations: ArrayInput[] = []; 32 | expectations.push('1'); 33 | expectations.push(2); 34 | ``` 35 | 36 | Unrecommended solutions: 37 | 38 | - Set "noImplicitAny" to `false` in your "tsconfig.json" 39 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7041.md: -------------------------------------------------------------------------------- 1 | ## TS7041 2 | 3 | > error TS7041: The containing arrow function captures the global value of '`this`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const myObject = { 9 | name: 'Benny', 10 | myMethod: () => { 11 | return this.name; 12 | }, 13 | }; 14 | ``` 15 | 16 | ### Fixed Code ✔️ 17 | 18 | Using `this` is not allowed in arrow functions ([source](https://github.com/Microsoft/TypeScript/issues/13768#issue-204165207)) because arrow functions aren't made to work with `call`, `apply` and/or `bind` methods ([source](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)). We have to replace our arrow function with an **anonymous function declaration** to prevent that our `this` context gets captured: 19 | 20 | ```ts 21 | const myObject = { 22 | name: 'Benny', 23 | myMethod: function () { 24 | return this.name; 25 | }, 26 | }; 27 | ``` 28 | 29 | Since ECMAScript 2015 (ES6) this can be shortened (Object Literal Property Value Shorthand) to: 30 | 31 | ```ts 32 | const myObject = { 33 | name: 'Benny', 34 | myMethod() { 35 | return this.name; 36 | }, 37 | }; 38 | ``` 39 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7044.md: -------------------------------------------------------------------------------- 1 | ## TS7044 2 | 3 | > error TS7044: Parameter '`a`' implicitly has an '`any`' type, but a better type may be inferred from usage. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const multiply = (a, b) => a * b; 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | From the body of the arrow function expression, TypeScript can see by the `*` that `a` and `b` may be of type `number`: 14 | 15 | ```ts 16 | const multiply = (a: number, b: number) => a * b; 17 | ``` 18 | -------------------------------------------------------------------------------- /errors/includes/TS7xxx/TS7053.md: -------------------------------------------------------------------------------- 1 | ## TS7053 2 | 3 | > error TS7053: Element implicitly has an '`any`' type because expression of type '`string`' can't be used to index type '`Person`'. No index signature with a parameter of type '`string`' was found on type '`Person`'. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | interface Person { 9 | name: string; 10 | } 11 | 12 | function getValue(person: Person, key: string): string { 13 | return person[key]; 14 | } 15 | ``` 16 | 17 | ### Fixed Code ✔️ 18 | 19 | There are multiple ways to solve the error. You can define an **index signature** for the `Person` interface which will allow all strings: 20 | 21 | 22 | {% codeblock lang:ts mark:2 %} 23 | interface Person { 24 | [index: string]: string; 25 | name: string; 26 | } 27 | 28 | function getValue(person: Person, key: string): string { 29 | return person[key]; 30 | } 31 | {% endcodeblock %} 32 | 33 | 34 | However, this is not recommend as it will allow you to access keys that are not defined (like `age`): 35 | 36 | 37 | {% codeblock lang:ts mark:10 %} 38 | interface Person { 39 | [index: string]: string; 40 | name: string; 41 | } 42 | 43 | function getValue(person: Person, key: string): string { 44 | return person[key]; 45 | } 46 | 47 | console.log(getValue({name: 'Benny'}, 'age')); // returns `undefined` 48 | {% endcodeblock %} 49 | 50 | 51 | The better solution is using the `keyof` type operator which creates a literal union of its keys: 52 | 53 | 54 | {% codeblock lang:ts mark:5 %} 55 | interface Person { 56 | name: string; 57 | } 58 | 59 | function getValue(person: Person, key: keyof Person): string { 60 | return person[key]; 61 | } 62 | {% endcodeblock %} 63 | 64 | -------------------------------------------------------------------------------- /errors/includes/TS80xxx/TS80005.md: -------------------------------------------------------------------------------- 1 | ## TS80005 2 | 3 | > error TS80005: 'require' call may be converted to an import. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | const pkg = require('../package.json'); 9 | ``` 10 | 11 | ### Fixed Code ✔️ 12 | 13 | ```ts 14 | import pkg from '../package.json'; 15 | ``` 16 | -------------------------------------------------------------------------------- /errors/includes/TS8xxx/TS8020.md: -------------------------------------------------------------------------------- 1 | ## TS8020 2 | 3 | > error TS8020: JSDoc types can only be used inside documentation comments. 4 | 5 | ### Broken Code ❌ 6 | 7 | ```ts 8 | function add(a: number, b: number, c: number?): number { 9 | return a + b; 10 | } 11 | ``` 12 | 13 | ### Fixed Code ✔️ 14 | 15 | If you wanted to make `c` optional: 16 | 17 | ```ts 18 | function add(a: number, b: number, c?: number): number { 19 | return a + b; 20 | } 21 | ``` 22 | 23 | If you wanted to document `c` with JSDoc: 24 | 25 | ```ts 26 | /** 27 | * @param a Initial quantity 28 | * @param b Amount to add 29 | * @param [c] Optional number to add 30 | */ 31 | function add(a: number, b: number, c: number): number { 32 | return a + b; 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /lefthook.yml: -------------------------------------------------------------------------------- 1 | pre-commit: 2 | parallel: true 3 | commands: 4 | linter: 5 | run: npx pretty-quick --staged 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@evilmartians/lefthook": "^1.4.3", 4 | "prettier": "^2.8.8", 5 | "pretty-quick": "^3.1.3" 6 | }, 7 | "scripts": { 8 | "fix": "npm run lint --fix", 9 | "lint": "prettier --ignore-path .gitignore --loglevel error --write \"**/*.{md,yml}\"", 10 | "reinstall": "lefthook install -a" 11 | } 12 | } 13 | --------------------------------------------------------------------------------