Common Errors

Discover the solution to your TypeScript problems with our comprehensive list of common TypeScript errors. Each entry includes the faulty code and its fixed version, ensuring you can quickly resolve any issue and get back to coding.

If you encounter errors that are not present in the list, feel free to submit them here: https://github.com/bennycode/typescript-errors/

If you’re interested in more TypeScript troubleshooting and best practices, check out our free TypeScript tutorials on YouTube. πŸ“Ί You can also follow TypeScript TV on Twitter to stay up to date. 🐀

image

All errors are categorized by the TypeScript team into the following ranges:


  1. 1. TS1002
  2. 2. TS1005
  3. 3. TS1006
  4. 4. TS1015
  5. 5. TS1016
  6. 6. TS1029
  7. 7. TS1036
  8. 8. TS1038
  9. 9. TS1039
  10. 10. TS1046
  11. 11. TS1055
  12. 12. TS1056
  13. 13. TS1064
  14. 14. TS1066
  15. 15. TS1068
  16. 16. TS1070
  17. 17. TS1095
  18. 18. TS1103
  19. 19. TS1109
  20. 20. TS1117
  21. 21. TS1127
  22. 22. TS1128
  23. 23. TS1149
  24. 24. TS1155
  25. 25. TS1160
  26. 26. TS1183
  27. 27. TS1192
  28. 28. TS1196
  29. 29. TS1202
  30. 30. TS1208
  31. 31. TS1218
  32. 32. TS1219
  33. 33. TS1225
  34. 34. TS1228
  35. 35. TS1232
  36. 36. TS1243
  37. 37. TS1244
  38. 38. TS1254
  39. 39. TS1259
  40. 40. TS1308
  41. 41. TS1337
  42. 42. TS1341
  43. 43. TS1355
  44. 44. TS1357
  45. 45. TS1361
  46. 46. TS1363
  47. 47. TS1368
  48. 48. TS1371
  49. 49. TS1375
  50. 50. TS1378
  51. 51. TS1385
  52. 52. TS1389
  53. 53. TS1431
  54. 54. TS1432
  55. 55. TS1434
  56. 56. TS1471
  57. 57. TS2300
  58. 58. TS2304
  59. 59. TS2305
  60. 60. TS2306
  61. 61. TS2307
  62. 62. TS2314
  63. 63. TS2315
  64. 64. TS2322
  65. 65. TS2335
  66. 66. TS2339
  67. 67. TS2344
  68. 68. TS2345
  69. 69. TS2348
  70. 70. TS2349
  71. 71. TS2351
  72. 72. TS2352
  73. 73. TS2355
  74. 74. TS2361
  75. 75. TS2362
  76. 76. TS2364
  77. 77. TS2365
  78. 78. TS2366
  79. 79. TS2367
  80. 80. TS2368
  81. 81. TS2369
  82. 82. TS2370
  83. 83. TS2371
  84. 84. TS2372
  85. 85. TS2377
  86. 86. TS2378
  87. 87. TS2390
  88. 88. TS2391
  89. 89. TS2393
  90. 90. TS2394
  91. 91. TS2395
  92. 92. TS2403
  93. 93. TS2411
  94. 94. TS2420
  95. 95. TS2428
  96. 96. TS2430
  97. 97. TS2440
  98. 98. TS2445
  99. 99. TS2448
  100. 100. TS2451
  101. 101. TS2454
  102. 102. TS2456
  103. 103. TS2459
  104. 104. TS2475
  105. 105. TS2476
  106. 106. TS2488
  107. 107. TS2497
  108. 108. TS2498
  109. 109. TS2503
  110. 110. TS2507
  111. 111. TS2511
  112. 112. TS2512
  113. 113. TS2515
  114. 114. TS2528
  115. 115. TS2531
  116. 116. TS2532
  117. 117. TS2533
  118. 118. TS2536
  119. 119. TS2538
  120. 120. TS2539
  121. 121. TS2540
  122. 122. TS2550
  123. 123. TS2551
  124. 124. TS2552
  125. 125. TS2554
  126. 126. TS2556
  127. 127. TS2558
  128. 128. TS2559
  129. 129. TS2564
  130. 130. TS2567
  131. 131. TS2571
  132. 132. TS2574
  133. 133. TS2577
  134. 134. TS2580
  135. 135. TS2582
  136. 136. TS2583
  137. 137. TS2584
  138. 138. TS2588
  139. 139. TS2595
  140. 140. TS2611
  141. 141. TS2613
  142. 142. TS2614
  143. 143. TS2616
  144. 144. TS2617
  145. 145. TS2632
  146. 146. TS2636
  147. 147. TS2637
  148. 148. TS2652
  149. 149. TS2654
  150. 150. TS2656
  151. 151. TS2661
  152. 152. TS2663
  153. 153. TS2664
  154. 154. TS2665
  155. 155. TS2668
  156. 156. TS2669
  157. 157. TS2677
  158. 158. TS2678
  159. 159. TS2680
  160. 160. TS2683
  161. 161. TS2684
  162. 162. TS2686
  163. 163. TS2687
  164. 164. TS2689
  165. 165. TS2691
  166. 166. TS2693
  167. 167. TS2694
  168. 168. TS2695
  169. 169. TS2706
  170. 170. TS2709
  171. 171. TS2713
  172. 172. TS2715
  173. 173. TS2717
  174. 174. TS2720
  175. 175. TS2722
  176. 176. TS2724
  177. 177. TS2730
  178. 178. TS2732
  179. 179. TS2739
  180. 180. TS2740
  181. 181. TS2741
  182. 182. TS2742
  183. 183. TS2749
  184. 184. TS2769
  185. 185. TS2774
  186. 186. TS2779
  187. 187. TS2786
  188. 188. TS2790
  189. 189. TS2792
  190. 190. TS2794
  191. 191. TS2802
  192. 192. TS2813
  193. 193. TS2814
  194. 194. TS4020
  195. 195. TS4025
  196. 196. TS4060
  197. 197. TS4063
  198. 198. TS4075
  199. 199. TS4081
  200. 200. TS4104
  201. 201. TS4112
  202. 202. TS4113
  203. 203. TS4114
  204. 204. TS5023
  205. 205. TS5024
  206. 206. TS5025
  207. 207. TS5042
  208. 208. TS5054
  209. 209. TS5055
  210. 210. TS5058
  211. 211. TS5069
  212. 212. TS5070
  213. 213. TS5083
  214. 214. TS5087
  215. 215. TS5101
  216. 216. TS6053
  217. 217. TS6059
  218. 218. TS6133
  219. 219. TS6138
  220. 220. TS6192
  221. 221. TS6196
  222. 222. TS6198
  223. 223. TS6504
  224. 224. TS7006
  225. 225. TS7008
  226. 226. TS7009
  227. 227. TS7010
  228. 228. TS7016
  229. 229. TS7017
  230. 230. TS7022
  231. 231. TS7023
  232. 232. TS7026
  233. 233. TS7027
  234. 234. TS7030
  235. 235. TS7031
  236. 236. TS7034
  237. 237. TS7041
  238. 238. TS7044
  239. 239. TS7053
  240. 240. TS8020
  241. 241. TS17000
  242. 242. TS17004
  243. 243. TS17009
  244. 244. TS18004
  245. 245. TS18016
  246. 246. TS18046
  247. 247. TS18048
  248. 248. TS80005

TS1002

error TS1002: Unterminated string literal.

Broken Code ❌

1
const text = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr

Fixed Code βœ”οΈ

You have to close the string literal with an ending ':

1
const text = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr';

If you want to support multiline text, then you would have to use string concatenation:

1
2
3
const text =
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, ' +
'sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.';

Another solution would be using a template literal:

1
2
const text = `Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 
sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.`;

TS1005

error TS1005: β€˜=’ expected.

Broken Code ❌

1
2
3
4
type Person {
age: number;
name: string;
}

Fixed Code βœ”οΈ

You need to assign your type declaration using the = character:

1
2
3
4
type Person = {
age: number;
name: string;
};

Alternatively you can declare an interface:

1
2
3
4
interface Person {
age: number;
name: string;
}

error TS1005: β€˜;’ expected.

Broken Code ❌

1
2
3
export function getNumbers(names: string[]) {
return names.map(name => {[name]: parseInt(name)});
}

Fixed Code βœ”οΈ

When using an arrow function expression, you can implicitly return values by wrapping the object literal in parentheses:

1
2
3
export function getNumbers(names: string[]) {
return names.map(name => ({[name]: parseInt(name)}));
}

TS1006

error TS1006: A file cannot have a reference to itself.

Broken Code ❌

index.d.ts
1
/// <reference path='index.d.ts' />

Fixed Code βœ”οΈ

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:

index.d.ts
1
/// <reference path='some-other-file.d.ts' />

TS1015

error TS1015: Parameter cannot have question mark and initializer.

Broken Code ❌

1
2
3
export function getName(firstName: string, lastName?: string = 'Doe'): string {
return `${firstName} ${lastName}`;
}

Fixed Code βœ”οΈ

1
2
3
export function getName(firstName: string, lastName: string = 'Doe'): string {
return `${firstName} ${lastName}`;
}

TS1016

error TS1016: A required parameter cannot follow an optional parameter.

Broken Code ❌

1
2
3
function createUser(firstName: string, lastName: string, middleName?: string, age: number) {
// ...
}

Fixed Code βœ”οΈ

The easiest way to fix the error is to make age optional as well:

1
2
3
function createUser(firstName: string, lastName: string, middleName?: string, age?: number) {
// ...
}

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”:

1
2
3
function createUser(firstName: string, lastName: string, age: number, middleName?: string) {
// ...
}

You could also make middleName non-optional:

1
2
3
function createUser(firstName: string, lastName: string, middleName: string, age?: number) {
// ...
}

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:

1
2
3
function createUser(firstName: string, lastName: string, middleName: string = '', age?: number) {
// ...
}

TS1029

error TS1029: β€˜public’ modifier must precede β€˜abstract’ modifier.

Broken Code ❌

1
2
3
abstract class Animal {
abstract public makeNoise(): string;
}

Fixed Code βœ”οΈ

They keywords public, private, and protected define the access to a class member. Access modifiers have to be defined first in TypeScript.

Solution 1:

1
2
3
abstract class Animal {
public abstract makeNoise(): string;
}

Solution 2:

The visibility is public by default, so you don’t have to explicitly declare it:

1
2
3
abstract class Animal {
abstract makeNoise(): string;
}

Video Tutorial


TS1036

error TS1036: Statements are not allowed in ambient contexts.

Broken Code ❌

1
2
3
4
5
import {APIClient} from '../../APIClient';

declare global {
client: APIClient;
}

Fixed Code βœ”οΈ

With declare global an 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:

1
2
3
declare global {
function client(): APIClient;
}

If you don’t want client to be a function, you have to use thevar` keyword:

1
2
3
declare global {
var client: APIClient;
}

TS1038

error TS1038: A β€˜declare’ modifier cannot be used in an already ambient context.

Broken Code ❌

1
2
3
declare global {
declare var REST_URL: string;
}

Fixed Code βœ”οΈ

1
2
3
declare global {
var REST_URL: string;
}

TS1039

error TS1039: Initializers are not allowed in ambient contexts.

Broken Code ❌

index.d.ts
1
2
3
4
5
declare module hexo {
var config = {

}
}

Fixed Code βœ”οΈ

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:

index.d.ts
1
2
3
declare module hexo {
var config: {};
}

TS1046

error TS1046: Top-level declarations in .d.ts files must start with either a β€˜declare’ or β€˜export’ modifier.

Broken Code ❌

index.d.ts
1
const MAGIC_NUMBER = 1337;

Fixed Code βœ”οΈ

If you want to export a constant from a definition file (d.ts), then you have to use the export modifier:

index.d.ts
1
export const MAGIC_NUMBER = 1337;

TS1055

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.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export const sendRequestWithCookie = async (
client: HttpClient,
config: AxiosRequestConfig,
engine: CRUDEngine
): AxiosPromise => {
const cookie: Cookie = await loadExistingCookie(engine);

if (!cookie.isExpired) {
config.headers = config.headers || {};
config.headers['Cookie'] = `zuid=${cookie.zuid}`;
config.withCredentials = true;
}

return client._sendRequest(config);
};

Fixed Code βœ”οΈ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export const sendRequestWithCookie = (
client: HttpClient,
config: AxiosRequestConfig,
engine: CRUDEngine
): AxiosPromise => {
return loadExistingCookie(engine).then((cookie: Cookie) => {
if (!cookie.isExpired) {
config.headers = config.headers || {};
config.headers['Cookie'] = `zuid=${cookie.zuid}`;
config.withCredentials = true;
}

return client._sendRequest(config);
});
};

TS1056

error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.

Broken Code ❌

User.ts
1
2
3
4
5
6
7
8
class User {
constructor(private firstName: string, private lastName: string) {
}

get fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"target": "es3"
}
}

Fixed Code βœ”οΈ

Set the β€œtarget” property in your β€œtsconfig.json” file to β€œes5” or higher:

tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"target": "es5"
}
}

TS1064

error TS1064: The return type of an async function or method must be the global Promise type. Did you mean to write β€˜Promise β€˜?

Broken Code ❌

1
2
3
async function myFunction(): string {
return 'test';
}

Fixed Code βœ”οΈ

If your function is asynchronous, your return value must be wrapped with Promise<...>:

1
2
3
async function myFunction(): Promise<string> {
return 'test';
}

TS1066

error TS1066: In ambient enum declarations member initializer must be constant expression.

Broken Code ❌

1
2
3
4
5
enum PreKeyAuth {
INVALID = 'Invalid',
UNKNOWN = 'Unknown',
VALID = 'Valid',
}

Fixed Code βœ”οΈ

Try to replace your enum declaration with a type:

1
type PreKeyAuth = 'Invalid' | 'Unknown' | 'Valid';

TS1068

error TS1068: Unexpected token. A constructor, method, accessor, or property was expected.

Broken Code ❌

1
2
3
4
5
6
7
8
class User {
constructor(private firstName: string, private lastName: string) {
}

function getName() {
return `${this.firstName} ${this.lastName}`;
}
}

Fixed Code βœ”οΈ

Functions that are part of a class are being called β€œmethod”. The method of a class is defined without the function keyword:

1
2
3
4
5
6
7
class User {
constructor(private firstName: string, private lastName: string) {}

getName() {
return `${this.firstName} ${this.lastName}`;
}
}

TS1070

error TS1070: β€˜private’ modifier cannot appear on a type member.

Broken Code ❌

1
2
3
interface Animal {
private name: string;
}

Fixed Code βœ”οΈ

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:

1
2
3
interface Animal {
name: string;
}

Video Tutorial


TS1095

error TS1095: A β€˜set’ accessor cannot have a return type annotation.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
export class Person {
private myName: string = 'unknown';

get name(): string {
return this.myName;
}

set name(newName: string): void {
this.myName = newName;
}
}

Fixed Code βœ”οΈ

You have to remove the return type from the β€œset” accessor:

1
2
3
4
5
6
7
8
9
10
11
export class Person {
private myName: string = 'unknown';

get name(): string {
return this.myName;
}

set name(newName: string) {
this.myName = newName;
}
}

TS1103

error TS1103: β€˜for await’ loops are only allowed within async functions and at the top levels of modules.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import fs from 'node:fs';
import readline from 'node:readline';

const inputStream = fs.createReadStream('file.csv');

function printLine(file: string): Promise<void> {
const rl = readline.createInterface({
input: inputStream,
crlfDelay: Infinity,
});

for await (const line of rl) {
console.log(line);
}
}

Fixed Code βœ”οΈ

You have to mark your function with the async keyword:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import fs from 'node:fs';
import readline from 'node:readline';

const inputStream = fs.createReadStream('file.csv');

async function printLine(file: string): Promise<void> {
const rl = readline.createInterface({
input: inputStream,
crlfDelay: Infinity,
});

for await (const line of rl) {
console.log(line);
}
}

TS1109

error TS1109: Expression expected.

Broken Code ❌

1
const lastName = throw new Error('Missing last name');

Fixed Code βœ”οΈ

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:

1
2
3
4
const lastName = undefined;
if (!lastName) {
throw new Error('Missing last name');
}

TS1117

error TS1117: An object literal cannot have multiple properties with the same name in strict mode.

Broken Code ❌

1
2
3
4
const objectLiteral = {
name: 'Benny',
name: 'Sofia',
};

Fixed Code βœ”οΈ

We can only have one value per property:

1
2
3
const objectLiteral = {
name: 'Benny',
};

TS1127

error TS1127: Invalid character.

Broken Code ❌

1
# My comment

Fixed Code βœ”οΈ

Unlike in Python, inline comments cannot begin with a single hash sign (#) in TypeScript. You must use 2 slashes:

1
// My comment

TS1128

error TS1128: Declaration or statement expected.

Broken Code ❌

1
=

Fixed Code βœ”οΈ

A declaration specifies the data and a statement specifies some action with that data:

1
2
3
4
// Declaration
let MY_NUMBER = 1;
// Statement
MY_NUMBER = MY_NUMBER + 1;

TS1149

error TS1149: File name differs from already included file name only in casing.

Broken Code ❌

This error occurs when you import the same file in two different files using two different casing styles (ex. camelCase and UpperCamelCase):

File A:

1
import {BaseTestPage} from './baseTestPage';

File B:

1
import {BaseTestPage} from './BaseTestPage';

Fixed Code βœ”οΈ

The error can be fixed by using the same casing style:

File A:

1
import {BaseTestPage} from './BaseTestPage';

File B:

1
import {BaseTestPage} from './BaseTestPage';

Alternatively, you can set forceConsistentCasingInFileNames to false in your β€œtsconfig.json” file:

tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"forceConsistentCasingInFileNames": false
}
}

TS1155

error TS1155: β€˜const’ declarations must be initialized.

Broken Code ❌

1
const name: string;

Fixed Code βœ”οΈ

1
const name: string = 'Benny';

Alternatively you can define a block-scoped local variable:

1
let name: string;

TS1160

error TS1160: Unterminated template literal.

Broken Code ❌

1
2
const text = `Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

Fixed Code βœ”οΈ

This error is similar to TS1002 but refers to the ending of a template literal. To fix it, we have to close the template literal with an ending `:

1
2
const text = `Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 
sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.`;

TS1183

error TS1183: An implementation cannot be declared in ambient contexts.

Broken Code ❌

index.d.ts
1
2
3
export function logSomething(error: unknown): void {
console.log('something');
}

Fixed Code βœ”οΈ

You cannot write a function implementation inside a declaration file (*.d.ts). You can only declare its signature:

index.d.ts
1
export function logSomething(error: unknown): void;

Alternatively, you can write your function implementation inside a source code file (*.ts).


TS1192

error TS1192: Module β€˜json5β€˜ has no default export.

Broken Code ❌

1
import json5 from 'json5';

Fixed Code βœ”οΈ

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:

tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"allowSyntheticDefaultImports": true
}
}

error TS1192: Module β€˜.../logdownβ€˜ has no default export.

Broken Code ❌

1
2
3
4
5
declare class Logdown {
// ...
}

export = Logdown;

Fixed Code βœ”οΈ

1
2
3
4
5
declare class Logdown {
// ...
}

export default Logdown;

error TS1192: β€˜export *β€˜ does not re-export a default.

Broken Code ❌

1
2
export * from './parseUrls';
export * from './runWhenReady';

You have to re-export a default (in this case coming from runWhenReady.ts):

Fixed Code βœ”οΈ

1
2
3
export * from './parseUrls';
export * from './runWhenReady';
export {default as default} from './runWhenReady';

TS1196

error TS1196: Catch clause variable type annotation must be β€˜any’ or β€˜unknown’ if specified.

Broken Code ❌

1
2
3
4
5
6
7
8
9
type MyError = {
code: number;
};

try {
// ...
} catch (error: MyError) {
console.log(error.code);
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Type Guard
function isMyError(error: any): error is MyError {
return typeof error.code === 'number';
}

type MyError = {
code: number;
};

try {
// ...
} catch (error: unknown) {
if (isMyError(error)) {
console.log(error.code);
}
}

Video Tutorial


TS1202

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.

Broken Code ❌

1
import sinon = require('sinon');

Fixed Code βœ”οΈ

1
import * as sinon from 'sinon';

TS1208

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.

Broken Code ❌

tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"isolatedModules": true
}
}
index.ts
1
2
3
require(`dotenv-defaults`).config({
path: '.env',
});

Fixed Code βœ”οΈ

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:

index.ts
1
2
3
4
5
require(`dotenv-defaults`).config({
path: '.env',
});

export default {};

TS1218

error TS1218: Export assignment is not supported when β€˜β€“module’ flag is β€˜system’.

Broken Code ❌

1
2
3
4
5
class LRUCache {
// ...
}

export = LRUCache;

Fixed Code βœ”οΈ

1
2
3
export class LRUCache {
// ...
}

TS1219

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.

Broken Code ❌

1
2
3
4
5
6
7
8
import {Injectable} from '@nestjs/common';

@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}

Fixed Code βœ”οΈ

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 package to shim the upcoming Metadata Reflection API for ECMAScript. For proper functionality the β€œemitDecoratorMetadata” option should also be set to true.


TS1225

error TS1225: Cannot find parameter β€˜errorβ€˜.

Broken Code ❌

1
2
3
const isError = (): input is Error => {
return input instanceof Error;
};

Fixed Code βœ”οΈ

A type predicate needs a parameter to validate:

1
2
3
const isError = (input: unknown): input is Error => {
return input instanceof Error;
};

TS1228

error TS1228: A type predicate is only allowed in return type position for functions and methods.

Broken Code ❌

1
2
3
function hasErrorCode(error: any) error is {code: string} {
return typeof (error && error.code) === 'string'
}

Fixed Code βœ”οΈ

You have to separate the argument list from the return type definition by a ::

1
2
3
function hasErrorCode(error: any): error is {code: string} {
return typeof (error && error.code) === 'string';
}

TS1232

error TS1232: An import declaration can only be used at the top level of a namespace or module.

Broken Code ❌

1
2
3
4
5
export function dumpPayload() {
const payload = {};
import {writeFileSync} from 'fs';
writeFileSync(`dump-${Date.now()}.json`, JSON.stringify(payload));
}

Fixed Code βœ”οΈ

1
2
3
4
5
6
import {writeFileSync} from 'fs';

export function dumpPayload() {
const payload = {};
writeFileSync(`dump-${Date.now()}.json`, JSON.stringify(payload));
}

TS1243

error TS1243: β€˜static’ modifier cannot be used with β€˜abstract’ modifier.

Solution

Broken Code ❌

1
2
3
abstract class CustomNumber {
abstract static getNumber(): number;
}

Your abstract class cannot define an abstract static function. You have to keep it static:

Fixed Code βœ”οΈ

1
2
3
4
5
abstract class CustomNumber {
static getNumber(): number {
return 1337;
};
}

error TS1243: β€˜async’ modifier cannot be used with β€˜abstract’ modifier.

Broken Code ❌

1
abstract async goto(): Promise<void>;

Fixed Code βœ”οΈ

1
abstract goto(): Promise<void>;

TS1244

error TS1244: Abstract methods can only appear within an abstract class.

Broken Code ❌

1
2
3
class Animal {
abstract makeNoise(): string;
}

Fixed Code βœ”οΈ

1
2
3
abstract class Animal {
abstract makeNoise(): string;
}

TS1254

error TS1254: A β€˜const’ initializer in an ambient context must be a string or numeric literal or literal enum reference.

Broken Code ❌

index.d.ts
1
2
3
declare module megalibrary {
const MEGA_NUMBER = {};
}

Fixed Code βœ”οΈ

index.d.ts
1
2
3
declare module megalibrary {
const MEGA_NUMBER = 1337;
}

TS1259

error TS1259: Module can only be default-imported using the β€˜esModuleInterop’ flag

Broken Code ❌

main.ts
1
import api from 'api';
tsconfig.json
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"compilerOptions": {
"lib": [
"dom",
"es6"
],
"module": "commonjs",
"moduleResolution": "node",
"outDir": "dist",
"rootDir": "src",
"target": "es6"
}
}

Fixed Code βœ”οΈ

tsconfig.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"compilerOptions": {
"esModuleInterop": true,
"lib": [
"dom",
"es6"
],
"module": "commonjs",
"moduleResolution": "node",
"outDir": "dist",
"rootDir": "src",
"target": "es6"
}
}

Note: You can enable the β€˜esModuleInterop’ flag also via the CLI:

1
tsc main.ts --esModuleInterop

TS1308

error TS1308: β€˜await’ expressions are only allowed within async functions and at the top levels of modules.ts.

Broken Code ❌

1
2
3
4
5
React.useEffect(() => {
const myPromise = Promise.resolve;
await myPromise();
console.log('Promise is resolved.');
}, []);

Fixed Code βœ”οΈ

You cannot use an await expression in an useEffect hook, but you can use legacy Promise calls:

1
2
3
4
5
6
React.useEffect(() => {
const myPromise = Promise.resolve;
myPromise().then(() => {
console.log('Promise is resolved.');
});
}, []);

Alternatively, you can use an IIFE (Immediately-invoked Function Expression) in your useEffect hook:

1
2
3
4
5
React.useEffect(() => {
(async () => {
await Promise.resolve();
})();
}, []);

TS1337

error TS1337: An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.

Broken Code ❌

1
2
3
export interface StreetMap {
[city: 'New York']: ['Broadway', 'Park Avenue'];
}

Fixed Code βœ”οΈ

1
2
3
export type StreetMap = {
'New York': ['Broadway', 'Park Avenue'];
};

Alternative:

1
2
3
export interface StreetMap {
[city: string]: ['Broadway', 'Park Avenue'];
}

error TS1337: An index signature parameter type cannot be a union type. Consider using a mapped object type instead.

Broken Code ❌

1
2
3
4
5
6
7
interface CustomError {
[key: string | number]: string | number;
}

const error: CustomError = {
401: 'Unauthorized',
};

Fixed Code βœ”οΈ

Solution with mapped object type:

1
2
3
4
5
6
7
type CustomError = {
[key in number | string]: string | number;
};

const error: CustomError = {
401: 'Unauthorized',
};

Alternative:

1
2
3
4
5
6
7
8
9
10
11
interface ErrorNumber {
[key: number]: string | number;
}

interface ErrorString {
[key: string]: string | number;
}

const error: ErrorNumber | ErrorString = {
401: 'Unauthorized',
};

TS1341

error TS1341: Class constructor may not be an accessor.

Broken Code ❌

1
2
3
4
5
6
7
8
class SomeClass {
get constructor() {
// ...
}
set constructor(value) {
// ...
}
}

Fixed Code βœ”οΈ

You can’t name accessors as constructor:

1
2
3
4
5
6
7
8
class SomeClass {
get builder() {
// ...
}
set builder(value) {
// ...
}
}

TS1355

error TS1355: A β€˜const’ assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.

Broken Code ❌

1
const result = (Math.random() < 0.5 ? 0 : 1) as const;

Fixed Code βœ”οΈ

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:

1
const result = Math.random() < 0.5 ? (0 as const) : (1 as const);

TS1357

error TS1357: An enum member name must be followed by a β€˜,β€˜, β€˜=β€˜, or β€˜}β€˜.

Broken Code ❌

1
2
3
enum GameAction {
RUN : 'RUN'
}

Fixed Code βœ”οΈ

1
2
3
enum GameAction {
RUN = 'RUN',
}

TS1361

error TS1361: β€˜Rangeβ€˜ cannot be used as a value because it was imported using β€˜import type’.

Broken Code ❌

1
2
3
4
5
6
7
8
9
import type { Range, TextEditor } from "vscode";

export class Ranger {
static getFullRange(editor: TextEditor): Range {
const lastLine = textEditor.document.lineAt(textEditor.document.lineCount - 1);
const firstLine = textEditor.document.lineAt(0);
return new Range(firstLine.range.start, lastLine.range.end);
}
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
10
import type { TextEditor } from 'vscode';
import { Range } from 'vscode';

export class Ranger {
static getFullRange(editor: TextEditor): Range {
const lastLine = textEditor.document.lineAt(textEditor.document.lineCount - 1);
const firstLine = textEditor.document.lineAt(0);
return new Range(firstLine.range.start, lastLine.range.end);
}
}

TS1363

error TS1363: A type-only import can specify a default import or named bindings, but not both.

Broken Code ❌

1
2
3
4
5
import type MyDog, {MyPerson} from './MyPerson';

export function printAge(personOrDog: MyPerson | MyDog) {
console.log(personOrDog.age);
}

Fixed Code βœ”οΈ

With type-only imports and exports 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:

1
2
3
4
5
6
import type {MyPerson} from './MyPerson';
import type MyDog from './MyPerson';

export function printAge(personOrDog: MyPerson | MyDog) {
console.log(personOrDog.age);
}

TS1368

error TS1368: Class constructor may not be a generator.

Broken Code ❌

1
2
3
4
5
class SomeClass {
*constructor() {
// ...
}
}

Fixed Code βœ”οΈ

You can’t name generators as constructor:

1
2
3
4
5
class SomeClass {
*builder() {
// ...
}
}

TS1371

error TS1371: This import is never used as a value and must use β€˜import type’ because β€˜importsNotUsedAsValues’ is set to β€˜error’.

Broken Code ❌

MyPerson.ts
1
2
3
4
export class MyPerson {
constructor(public name: string, public age: number) {
}
}
printAge.ts
1
2
3
4
5
import {MyPerson} from './MyPerson';

export function printAge(person: MyPerson) {
console.log(person.age);
}

Fixed Code βœ”οΈ

Solution 1:

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:

printAge.ts
1
2
3
4
5
import type {MyPerson} from './MyPerson';

export function printAge(person: MyPerson) {
console.log(person.age);
}

Solution 2:

Use the class also as a value and not just a type:

printAge.ts
1
2
3
4
5
6
7
8
import {MyPerson} from './MyPerson';

export function printAge(person: MyPerson) {
console.log(person.age);
}

const benny = new MyPerson('Benny', 35);
printAge(benny);

Solution 3:

You can also set β€œimportsNotUsedAsValues” to β€œpreserve” which is not recommended.


TS1375

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.

Broken Code ❌

1
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');

Fixed Code βœ”οΈ

1
2
3
export {};

const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');

TS1378

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.

Broken Code ❌

tsconfig.json
1
2
3
4
5
6
7
8
9
{
"compilerOptions": {
"lib": ["es2017"],
"module": "commonjs",
"outDir": "dist",
"rootDir": "src",
"target": "es6"
}
}

Fixed Code βœ”οΈ

tsconfig.json
1
2
3
4
5
6
7
8
9
{
"compilerOptions": {
"lib": ["es2017"],
"module": "esnext",
"outDir": "dist",
"rootDir": "src",
"target": "es2017"
}
}

TS1385

error TS1385: Function type notation must be parenthesized when used in a union type.

Broken Code ❌

1
type MyCallback = () => number | () => string

Fixed Code βœ”οΈ

When using a union type, you have to put additional function types in parentheses:

1
type MyCallback = () => number | (() => string);

TS1389

error TS1389: β€˜this’ is not allowed as a variable declaration name.

Broken Code ❌

1
const this = 'something';

Fixed Code βœ”οΈ

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.

That’s why you have to choose a different name:

1
const that = 'something';

TS1431

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.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
const inputStream = fs.createReadStream('file.csv');

const rl = readline.createInterface({
input: inputStream,
crlfDelay: Infinity,
});

for await (const line of rl) {
console.log(line);
}

Fixed Code βœ”οΈ

Just add the imports for the fs module and readline module in order to turn your code into a module itself:

1
2
3
4
5
6
7
8
9
10
11
12
13
import fs from 'node:fs';
import readline from 'node:readline';

const inputStream = fs.createReadStream('file.csv');

const rl = readline.createInterface({
input: inputStream,
crlfDelay: Infinity,
});

for await (const line of rl) {
console.log(line);
}

TS1432

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.

Broken Code ❌

start.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import fs from 'node:fs';
import readline from 'node:readline';

const file = 'abc.csv';

const fileStream = fs.createReadStream(file);

const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});

for await (const line of rl) {
console.log(`Line from file: ${line}`);
}
tsconfig.json
1
2
3
4
5
6
7
{
"compilerOptions": {
"lib": ["es2017"],
"module": "commonjs",
"target": "es6"
}
}

Fixed Code βœ”οΈ

The error is similar to TS1378 and needs an adjustment in the tsconfig.json file:

tsconfig.json
1
2
3
4
5
6
7
{
"compilerOptions": {
"lib": ["es2017"],
"module": "esnext",
"target": "es2017"
}
}

TS1434

error TS1434: Unexpected keyword or identifier.

Broken Code ❌

1
2
3
class MyClass {
static static ID: number = 1337;
}

Fixed Code βœ”οΈ

You have to remove the duplicate static keyword:

1
2
3
class MyClass {
static ID: number = 1337;
}

TS1471

error 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.

Broken Code ❌

1
import {FocusTrap} from '@headlessui/react';

Fixed Code βœ”οΈ

Using a dynamic import:

1
const {FocusTrap} = await import('@headlessui/react');

TS2300

error TS2300: Duplicate identifier β€˜name’.

Broken Code ❌

Objects don’t support multiple properties with the same name:

1
2
3
4
const objectLiteral = {
name: 'Benny',
name: 'Sofia',
};

Fixed Code βœ”οΈ

To fix the error we have to remove the duplicated property:

1
2
3
const objectLiteral = {
name: 'Sofia',
};

TS2304

error TS2304: Cannot find name β€˜world’.

Broken Code ❌

1
console.log(world.name);

Fixed Code βœ”οΈ

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):

1
2
3
4
5
declare var world: {
name: string;
};

console.log(world.name);

error TS2304: Cannot find name β€˜Promise’

Broken Code ❌

1
2
3
4
5
6
7
8
9
// ...

public load_prekey(prekey_id: number): Promise<Proteus.keys.PreKey> {
return new Promise((resolve) => {
resolve(42);
});
}

// ...

Fixed Code βœ”οΈ

Install es6-promise type definitions with the typings tool.

1
typings install dt~es6-promise --global --save

Adding the following line to the beginning of every file using definitions from es6-promise.

1
2
3
4
5
6
7
8
9
10
11
/// <reference path='es6-promise.d.ts' />

...

public load_prekey(prekey_id: number): Promise<Proteus.keys.PreKey> {
return new Promise((resolve) => {
resolve(42);
});
}

...

error TS2304: Cannot find name β€˜Promise’

Broken Code ❌

1
const UUID = require('uuidjs');

Fixed Code βœ”οΈ

1
npm install @types/node --save-dev

error TS2304: Cannot find name β€˜FC’.

Broken Code ❌

1
2
3
4
5
import React from 'react';

const App: FC = (): JSX.Element => {
return <></>;
};

Fixed Code βœ”οΈ

1
2
3
4
5
import React, {FC} from 'react';

const App: FC = (): JSX.Element => {
return <></>;
};

TS2305

error TS2305: Module β€˜./sumβ€˜ has no exported member β€˜multiplyβ€˜.

Broken Code ❌

sum.ts
1
2
3
export function sum(a: number, b: number): number {
return a + b;
}
main.ts
1
2
3
import { multiply } from './sum';

console.log(multiply(1, 2));

Fixed Code βœ”οΈ

The file β€œsum.ts” exports a function named β€œsum”, so we have to fix the named import in our β€œmain.ts” file:

main.ts
1
2
3
import { sum } from './sum';

console.log(sum(1, 2));

TS2306

error TS2306: File β€˜add.tsβ€˜ is not a module.

Broken Code ❌

add.ts
1
2
3
function add(a: number, b: number): number {
return a + b;
}
main.ts
1
2
3
import { add } from './add';

console.log(add(1000, 337));

Fixed Code βœ”οΈ

The error TS2306 signals that the file (add.ts) can be found (otherwise it would throw error TS2307) but does not provide the necessary exports. We can solve this with a named export:

add.ts
1
2
3
export function add(a: number, b: number): number {
return a + b;
}

Alternatively we can use a default export:

add.ts
1
2
3
export default function add(a: number, b: number): number {
return a + b;
}

Using a default export requires that we also adjust our import statement in main.ts (otherwise we would end up with error TS2614):

main.ts
1
2
3
import add from './add';

console.log(add(1000, 337));

Video Tutorial


TS2307

error TS2307: Cannot find module β€˜events’ or its corresponding type declarations.

Broken Code ❌

You are importing from a core Node.js module (e.g. event) without having Node.js type definitions installed:

1
import {EventEmitter} from 'events';

Fixed Code βœ”οΈ

Import Node.js type definitions first in order to use Node.js core modules:

1
npm install @types/node

More: Error TS2307: Cannot find module events


TS2314

error TS2314: Generic type β€˜Omitβ€˜ requires 2 type argument(s).

Broken Code ❌

1
2
3
4
export interface SerializedBatchedCandle extends Omit<BatchedCandle, 'close', 'open'> {
open: string;
close: string;
}

Fixed Code βœ”οΈ

When using the Omit utility type, you have to list property overwrites with a pipe (|):

1
2
3
4
export interface SerializedBatchedCandle extends Omit<BatchedCandle, 'close' | 'closeAsk'> {
close: string;
closeAsk: string;
}

error TS2314: Generic type β€˜ReadonlyArray β€˜ requires 1 type argument(s).

Broken Code ❌

1
const array: ReadonlyArray = [1, 2, 3] as const;

Fixed Code βœ”οΈ

When using a generic (in this case ReadonlyArray<T>), then you have to pass a type argument to it:

1
const array: ReadonlyArray<number> = [1, 2, 3] as const;

TS2315

error TS2315: Type β€˜CustomRequestβ€˜ is not generic.

Broken Code ❌

1
2
3
4
5
6
7
8
9
type CustomRequest = {
url: string;
data: string;
};

const request: CustomRequest<string> = {
url: 'https://typescript.tv/',
data: 'example',
};

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
type CustomRequest<CustomType> = {
url: string;
data: CustomType;
};

const request: CustomRequest<string> = {
url: 'https://typescript.tv/',
data: 'example',
};

TS2322

error TS2322: Type β€˜string’ is not assignable to type β€˜number’.

Broken Code ❌

1
2
3
export function add(a: number, b: number): number {
return `${a + b}`;
}

Fixed Code βœ”οΈ

The type of the returned value must match the return type specified in the function signature:

1
2
3
export function add(a: number, b: number): number {
return parseInt(`${a + b}`, 10);
}

Video Tutorial


TS2335

error TS2335: β€˜super’ can only be referenced in a derived class.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
13
abstract class Animal {
abstract makeNoise(): string;
}

class Cat {
constructor() {
super();
}

makeNoise(): string {
return 'Meow!';
}
}

Fixed Code βœ”οΈ

Your derived class has to β€œextend” the base class:

1
2
3
4
5
6
7
8
9
10
11
12
13
abstract class Animal {
abstract makeNoise(): string;
}

class Cat extends Animal {
constructor() {
super();
}

makeNoise(): string {
return 'Meow!';
}
}

TS2339

error TS2339: Property β€˜widthβ€˜ does not exist on type β€˜Shapeβ€˜.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
type Shape = {
kind: 'rectangle' | 'square';
};

type Rectangle = {
kind: 'rectangle';
width: number;
height: number;
} & Shape;

type Square = {
kind: 'square';
size: number;
} & Shape;

function handleShape(shape: Shape): void {
switch (shape.kind) {
case 'rectangle':
console.log(shape.width);
break;
case 'square':
console.log(shape.size);
break;
}
}

Fixed Code βœ”οΈ

You can create discriminated unions by sharing a single field (e.g. kind) in your type definitions and using a union type in connection with a switch-case statement that helps the TypeScript compiler to distinguish the different types:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type Rectangle = {
kind: 'rectangle';
width: number;
height: number;
}

type Square = {
kind: 'square';
size: number;
}

type Shape = Rectangle | Square;

function handleShape(shape: Shape): void {
switch (shape.kind) {
case 'rectangle':
console.log(shape.width);
break;
case 'square':
console.log(shape.size);
break;
}
}

error TS2339: Property β€˜popβ€˜ does not exist on type β€˜readonly [1, 2, 3]β€˜.

Broken Code ❌

1
2
const array = [1, 2, 3] as const;
array.pop();

When using a const assertion on an array, then your array becomes readonly (immutable), so you cannot modify its elements using in-place operations such as pop. You will have to make your array mutable:

1
2
const array: number[] = [1, 2, 3];
array.pop();

TS2344

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; }β€˜.

Broken Code ❌

1
2
3
4
5
6
function increaseAge<T extends { age: number }>(data: T): T {
data.age += 1;
return data;
}

increaseAge<{ name: string }>({age: 25, name: 'Benny'});

Fixed Code βœ”οΈ

When passing a type argument, the required properties of the type variable (T) must be matched:

1
2
3
4
5
6
function increaseAge<T extends { age: number }>(data: T): T {
data.age += 1;
return data;
}

increaseAge<{ age: number, name: string }>({age: 25, name: 'Benny'});

As an alternative, type argument inference can be used:

1
2
3
4
5
6
function increaseAge<T extends { age: number }>(data: T): T {
data.age += 1;
return data;
}

increaseAge({age: 25, name: 'Benny'});

TS2345

error TS2345: Argument of type β€˜numberβ€˜ is not assignable to parameter of type β€˜TimerHandlerβ€˜.

Broken Code ❌

1
2
3
4
5
function add(a: number, b: number): number {
return a + b;
}

setTimeout(add(1000, 337), 5000);

Fixed Code βœ”οΈ

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:

1
2
3
4
5
function add(a: number, b: number): number {
return a + b;
}

setTimeout(() => add(1000, 337), 5000);

Video Tutorial


TS2348

error TS2348: Value of type β€˜typeof BaseN’ is not callable. Did you mean to include β€˜new’?

Broken Code ❌

1
2
3
import {BaseN} from 'js-combinatorics';

const iterator = BaseN([1, 2, 3], 2);

Fixed Code βœ”οΈ

1
2
3
import {BaseN} from 'js-combinatorics';

const iterator = new BaseN([1, 2, 3], 2);

TS2349

error TS2349: Cannot invoke an expression whose type lacks a call signature. Type β€˜Promiseβ€˜ has no compatible call signatures.

Broken Code ❌

1
2
3
function bugged(param: Promise<Object>): void {
param().then(() => console.log('error TS2349'));
}

Fixed Code βœ”οΈ

1
2
3
function bugged(param: Promise<Object>): void {
param.then(() => console.log('error TS2349'));
}

TS2351

error TS2351: This expression is not constructable. Type β€˜EMAβ€˜ has no construct signatures.

Broken Code ❌

RSI.ts
1
2
3
4
5
6
7
export class RSI {
private readonly avgGain: MovingAverage;

constructor(private readonly interval: number, Indicator: EMA) {
this.avgGain = new Indicator(this.interval);
}
}
EMA.ts
1
export class EMA {}

Fixed Code βœ”οΈ

RSI.ts
1
2
3
4
5
6
7
export class RSI {
private readonly avgGain: MovingAverage;

constructor(private readonly interval: number, Indicator: typeof EMA) {
this.avgGain = new Indicator(this.interval);
}
}

TS2352

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.

Broken Code ❌

1
2
3
4
5
6
7
8
9
type Person = {
firstName: string;
age: number;
};

const myObject = {
name: 'Benny',
age: 34,
} as Person;

Fixed Code βœ”οΈ

Make sure all properties of your object match the properties of your declared type:

1
2
3
4
5
6
7
8
9
type Person = {
firstName: string;
age: number;
};

const myObject = {
firstName: 'Benny',
age: 34,
} as Person;

Alternative but not recommended: Convert your object to unknown first:

1
2
3
4
5
6
7
8
9
type Person = {
firstName: string;
age: number;
};

const myObject = {
name: 'Benny',
age: 34,
} as unknown as Person;

TS2355

error TS2355: A function whose declared type is neither β€˜void’ nor β€˜any’ must return a value.

Broken Code ❌

1
2
3
getName(): string {

}

Fixed Code βœ”οΈ

1
2
3
getName(): string {
return 'Benny';
}

TS2361

error TS2361: The right-hand side of an β€˜in’ expression must not be a primitive.

Broken Code ❌

1
2
3
4
5
import axios, {AxiosError} from 'axios';

const isAxiosError = (error: unknown): error is AxiosError => {
return 'isAxiosError' in error;
};

Fixed Code βœ”οΈ

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:

1
2
3
4
5
import axios, {AxiosError} from 'axios';

const isAxiosError = (error: object): error is AxiosError => {
return 'isAxiosError' in error;
};

An alternative solution would be to use a type assertion on the right-hand side of the β€˜in’ expression:

1
2
3
const isAxiosError = (error: unknown): error is AxiosError => {
return 'isAxiosError' in (error as AxiosError);
};

TS2362

error TS2362: The left-hand side of an arithmetic operation must be of type β€˜any’, β€˜number’, β€˜bigint’ or an enum type.

Broken Code ❌

1
2
3
const userName = {name: 'Benny'};
const userAge = {age: 35};
const user = userName & userAge;

Fixed Code βœ”οΈ

When you want to merge two objects, you have a multitude of possibilities:

Spread Syntax

1
2
3
4
5
6
const userName = {name: 'Benny'};
const userAge = {age: 35};
const user = {
...userName,
...userAge,
};

Object.assign

1
2
3
const userName = {name: 'Benny'};
const userAge = {age: 35};
const user = Object.assign({}, userName, userAge);

TS2364

error TS2364: The left-hand side of an assignment expression must be a variable or a property access.

Broken Code ❌

1
1 = 1;

Fixed Code βœ”οΈ

Using a variable on the left-hand side assignment:

1
const a = 1;

TS2365

error TS2365: Operator β€˜+’ cannot be applied to types β€˜number’ and β€˜object’.

Broken Code ❌

1
2
3
export function add(a: number, b: object): number {
return a + b;
}

Fixed Code βœ”οΈ

You can use the + operator only with equivalent data types (strings + strings or numbers + numbers):

1
2
3
export function add(a: number, b: number): number {
return a + b;
}

TS2366

error TS2366: Function lacks ending return statement and return type does not include β€˜undefined’.

Broken Code ❌

1
2
3
4
5
6
7
8
export function getInterestRate(years: 1 | 2 | 3): number {
switch (years) {
case 1:
return 1.75;
case 2:
return 2.96;
}
}

Fixed Code βœ”οΈ

The switch-case statement isn’t handling all cases from every possible input. We can solve that by defining a default case:

1
2
3
4
5
6
7
8
9
10
export function getInterestRate(years: 1 | 2 | 3): number {
switch (years) {
case 1:
return 1.75;
case 2:
return 2.96;
default:
return 3;
}
}

Another solution would be to implement the missing case for 3:

1
2
3
4
5
6
7
8
9
10
export function getInterestRate(years: 1 | 2 | 3): number {
switch (years) {
case 1:
return 1.75;
case 2:
return 2.96;
case 3:
return 3;
}
}

Video Tutorial


TS2367

error TS2367: This condition will always return β€˜false’ since the types β€˜{ message: string; }[] | undefined’ and β€˜number’ have no overlap.

Broken Code ❌

1
2
3
4
5
function myTest(errors: {message: string}[]): void {
if (errors === 0) {
throw new Error();
}
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
function myTest(errors: {message: string}[]): void {
if (errors.length === 0) {
throw new Error();
}
}

TS2368

error TS2368: Type parameter name cannot be β€˜number’.

Broken Code ❌

1
2
3
export interface SimpleNumberIndicator<number> {
update(price: T): T;
}

Fixed Code βœ”οΈ

The easiest way to fix the error is to make age optional as well:

1
2
3
export interface SimpleNumberIndicator<T = number> {
update(price: T): T;
}

TS2369

error TS2369: A parameter property is only allowed in a constructor implementation.

Broken Code ❌

1
2
3
class MyMessenger {
constructor(public message: string);
}

Fixed Code βœ”οΈ

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:

1
2
3
class MyMessenger {
constructor(public message: string) {}
}

TS2370

error TS2370: A rest parameter must be of an array type.

Broken Code ❌

1
2
3
4
5
function sum(...array: number): number {
return array.reduce((a, b) => a + b);
}

console.log(sum(...[1, 2, 3, 4, 5]));

Fixed Code βœ”οΈ

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:

1
2
3
4
5
function sum(...array: number[]): number {
return array.reduce((a, b) => a + b);
}

console.log(sum(...[1, 2, 3, 4, 5]));

TS2371

error TS2371: A parameter initializer is only allowed in a function or constructor implementation.

Broken Code ❌

1
2
3
4
function add(a: number, b: number, c: number = 0): number;
function add(a: number | string, b: number | string, c: number | string = 0): number {
return parseInt(`${a}`, 10) + parseInt(`${b}`, 10);
}

Fixed Code βœ”οΈ

Remove parameter initializer from function overload:

1
2
3
4
function add(a: number, b: number, c: number): number;
function add(a: number | string, b: number | string, c: number | string = 0): number {
return parseInt(`${a}`, 10) + parseInt(`${b}`, 10);
}

TS2372

error TS2372: Parameter β€˜scoreβ€˜ cannot reference itself.

Broken Code ❌

1
2
3
function printScore(score: number = score): void {
console.log(score);
}

Fixed Code βœ”οΈ

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:

1
2
3
function printScore(score: number = 0): void {
console.log(score);
}

TS2377

error TS2377: Constructors for derived classes must contain a β€˜super’ call.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
abstract class Animal {
abstract name: string;
}

class Dog extends Animal {
public name;

constructor(name: string) {
this.name = name;
}
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
10
11
12
abstract class Animal {
abstract name: string;
}

class Dog extends Animal {
public name;

constructor(name: string) {
super();
this.name = name;
}
}

Video Tutorial


TS2378

error TS2378: A β€˜get’ accessor must return a value.

Broken Code ❌

1
2
3
get name() {

}

Fixed Code βœ”οΈ

1
2
3
get name(): string {
return 'Benny';
}

TS2390

error TS2390: Constructor implementation is missing.

Broken Code ❌

1
2
3
class MyMessenger {
constructor(public message: string);
}

Fixed Code βœ”οΈ

A constructor implementation must be put in curly brackets:

1
2
3
class MyMessenger {
constructor(public message: string) {}
}

TS2391

error TS2391: Function implementation is missing or not immediately following the declaration.

Broken Code ❌

1
2
3
4
abstract class Animal {
abstract name: string;
makeNoise(): string;
}

Fixed Code βœ”οΈ

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.

Solution 1:

To solve the problem, we can mark makeNoise with the abstract keyword. That will enforce derived classes to implement this method on their own:

1
2
3
4
abstract class Animal {
abstract name: string;
abstract makeNoise(): string;
}

Solution 2:

Another solution is to provide a base implementation for makeNoise:

1
2
3
4
5
6
abstract class Animal {
abstract name: string;
makeNoise(): string {
return 'Woof';
}
}

Video Tutorial


TS2393

error TS2393: Duplicate function implementation.

Broken Code ❌

1
2
3
function add(a: number, b: number) {
return a + b;
}

Fixed Code βœ”οΈ

This error may occur when you have multiple files within the same project that implement the same function with the same name. To resolve this issue, you need to configure TypeScript to recognize a file as a script rather than a module. This can be achieved by setting the β€œmoduleDetection” option to β€œforce” instead of the default β€œauto”:

tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"moduleDetection": "force"
}
}

TS2394

error TS2394: This overload signature is not compatible with its implementation signature.

Broken Code ❌

The implementation does not match all signatures:

1
2
3
4
5
function sum(a: number, b: number): number;
function sum(a: string, b: string): string;
function sum(a: number | string, b: number | string) {
return `${parseInt(a + '', 10) + parseInt(b + '', 10)}`;
}

Fixed Code βœ”οΈ

To match the first function overload, we have to add code to our function body which can also return a number:

1
2
3
4
5
6
7
8
function sum(a: number, b: number): number;
function sum(a: string, b: string): string;
function sum(a: number | string, b: number | string) {
if (typeof a === 'number' && typeof b === 'number') {
return a + b;
}
return `${parseInt(a + '', 10) + parseInt(b + '', 10)}`;
}

Video Tutorial


TS2395

error TS2395: Individual declarations in merged declaration β€˜Reactβ€˜ must be all exported or all local.

Broken Code ❌

index.d.ts
1
2
3
4
5
import * as React from 'react';

declare namespace React {
type StatelessComponent<P> = React.FunctionComponent<P>;
}

Fixed Code βœ”οΈ

Make sure to export your additional declaration:

index.d.ts
1
2
3
4
5
import * as React from 'react';

export declare namespace React {
type StatelessComponent<P> = React.FunctionComponent<P>;
}

TS2403

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β€˜.

Broken Code ❌

1
var window: any = window || null;

Fixed Code βœ”οΈ

1
var window: Window & typeof globalThis = window || null;

TS2411

error TS2411: Property β€˜age’ of type β€˜number’ is not assignable to β€˜string’ index type β€˜string’.

Broken Code ❌

1
2
3
4
5
interface Person {
[key: string]: string;
age: number;
name: string;
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
interface Person {
[key: string]: number | string;
age: number;
name: string;
}

TS2420

error TS2420: Class β€˜Dog’ incorrectly implements interface β€˜Animal’. Property β€˜name’ is private in type β€˜Dog’ but not in type β€˜Animal’.

Broken Code ❌

1
2
3
4
5
6
7
interface Animal {
name: string;
}

class Dog implements Animal {
constructor(private name: string = 'Bobby') {}
}

Fixed Code βœ”οΈ

The Animal interface defines a public name member. The name property in our Dog class must therefore also be public:

1
2
3
4
5
6
7
interface Animal {
name: string;
}

class Dog implements Animal {
constructor(public name: string = 'Bobby') {}
}

Video Tutorial


TS2428

error TS2428: All declarations of β€˜Strategyβ€˜ must have identical type parameters.

Broken Code ❌

Strategy.ts
1
2
3
4
5
6
7
8
9
10
11
enum TOPIC {
ON_LOGOUT = 'ON_LOGOUT',
}

export interface Strategy {
on(event: TOPIC.ON_LOGOUT, listener: (reason: string) => void): this;
}

export abstract class Strategy<SpecificConfig extends StrategyConfig> extends EventEmitter {
// ...
}

Fixed Code βœ”οΈ

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.

Strategy.ts
1
2
3
4
5
6
7
8
9
10
11
enum TOPIC {
ON_LOGOUT = 'ON_LOGOUT',
}

export interface Strategy<SpecificConfig extends StrategyConfig> {
on(event: TOPIC.ON_LOGOUT, listener: (reason: string) => void): this;
}

export abstract class Strategy<SpecificConfig extends StrategyConfig> extends EventEmitter {
// ...
}

TS2430

error TS2430: Interface β€˜StockExchangeβ€˜ incorrectly extends interface β€˜Exchangeβ€˜.

Broken Code ❌

1
2
3
4
5
6
7
interface Exchange {
address: string;
}

export interface StockExchange extends Exchange {
address?: string;
}

Fixed Code βœ”

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:

1
2
3
4
5
6
7
interface Exchange {
address: string;
}

export interface StockExchange extends Exchange {
address?: string;
}

TS2440

error TS2440: Import declaration conflicts with local declaration of β€˜Reactβ€˜.

Broken Code ❌

main.ts
1
2
3
4
5
import React from 'react';

declare module React {
type MyCustomType<P> = void;
}

Fixed Code βœ”οΈ

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:

index.d.ts
1
2
3
declare namespace React {
type MyCustomType<P> = void;
}

TS2445

error TS2445: Property β€˜makeNoise’ is protected and only accessible within class β€˜Dog’ and its subclasses.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
abstract class Animal {
protected abstract makeNoise(): string;
}

class Dog extends Animal {
protected makeNoise(): string {
return 'Woof!';
}
}

const laika = new Dog();
laika.makeNoise();

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
10
11
12
abstract class Animal {
protected abstract makeNoise(): string;
}

class Dog extends Animal {
public makeNoise(): string {
return 'Woof!';
}
}

const laika = new Dog();
laika.makeNoise();

Video Tutorial


TS2448

error TS2448: Block-scoped variable β€˜add’ used before its declaration.

Broken Code ❌

Function expressions cannot be hoisted (used before they are declared):

1
2
3
4
5
add(1, 2);

const add = (a: number, b: number): number => {
return a + b;
};

Fixed Code βœ”οΈ

Turn your function expression into a function declaration (which can be hoisted):

1
2
3
4
5
add(1, 2);

function add(a: number, b: number): number {
return a + b;
}

TS2451

error TS2451: Cannot redeclare block-scoped variable β€˜windowβ€˜.

Broken Code ❌

1
const window = 'blue';

Fixed Code βœ”οΈ

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:

1
const myWindow = 'blue';

TS2454

error TS2454: Variable β€˜myFavoriteNumber’ is used before being assigned.

Broken Code ❌

1
2
3
4
export function myNumber(): number {
let myFavoriteNumber: number;
return myFavoriteNumber;
}

Fixed Code βœ”οΈ

1
2
3
4
5
export function myNumber(): number {
let myFavoriteNumber: number;
myFavoriteNumber = 72;
return myFavoriteNumber;
}

or

1
2
3
4
export function myNumber(): number {
let myFavoriteNumber: number = 72;
return myFavoriteNumber;
}

TS2456

error TS2456: Type alias β€˜MyValueβ€˜ circularly references itself.

Broken Code ❌

1
type MyValue = number | string | Record<string, MyValue>;

Fixed Code βœ”οΈ

When defining a recursive type, you have to use the object syntax:

1
type MyValue = number | string | {[key: string]: MyValue};

TS2459

error TS2459: Module β€˜./myFunctionβ€˜ declares β€˜myFunctionβ€˜ locally, but it is not exported.

Broken Code ❌

myFunction.ts
1
2
3
4
5
function myFunction(a: number, b: number): number {
return a + b;
}

export {}
index.ts
1
2
3
import {myFunction} from './myFunction';

myFunction(1, 2);

Fixed Code βœ”οΈ

When you want to import your function in another file, you have to make sure that it is exported using the export keyword:

myFunction.ts
1
2
3
export function myFunction(a: number, b: number): number {
return a + b;
}
index.ts
1
2
3
import {myFunction} from './myFunction';

myFunction(1, 2);

TS2475

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.

Broken Code ❌

1
2
3
4
5
6
7
export const enum TIME_INTERVAL {
ONE_MINUTE = '1m',
THREE_MINUTES = '3m',
FIVE_MINUTES = '5m',
}

console.log(Object.values(TIME_INTERVAL));

Fixed Code βœ”οΈ

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.

If you want that TypeScript creates JS code for your enum definition, then you have to remove the const keyword:

1
2
3
4
5
6
7
export enum TIME_INTERVAL {
ONE_MINUTE = '1m',
THREE_MINUTES = '3m',
FIVE_MINUTES = '5m',
}

console.log(Object.values(TIME_INTERVAL));

TS2476

error TS2476: A const enum member can only be accessed using a string literal.

Broken Code ❌

1
2
3
4
5
6
const enum OrderSide {
BUY = 'buy',
SELL = 'sell',
}

console.log(OrderSide[0]);

Fixed Code βœ”οΈ

Constant enumerations can only be accessed using key names:

1
2
3
4
5
6
const enum OrderSide {
BUY = 'buy',
SELL = 'sell',
}

console.log(OrderSide.BUY);

If you want to access enums by indices, you must remove the const keyword and values from your enum:

1
2
3
4
5
6
enum OrderSide {
BUY,
SELL,
}

console.log(OrderSide[0]);

⚠️ Be aware that this may become unsafe as you may unintentionally access indices that are not defined.


TS2488

error TS2488: Type β€˜{ [month: number]: string; }β€˜ must have a β€˜[Symbol.iterator]()β€˜ method that returns an iterator.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
const months: {
[month: number]: string;
} = {
1: 'January',
2: 'February',
};

for (const month of months) {
console.log(month);
}

Fixed Code βœ”οΈ

The simplest way to loop over an object is to create an iterable object by using Object.entries.

Another method is to add a property called [Symbol.iterator] to your object. The value of this property has to return an iterator. Here you can learn how to create an iterator.

1
2
3
4
5
6
7
8
9
10
11
const months: {
[month: number]: string;
} = {
1: 'January',
2: 'February',
};

const entries = Object.entries(months);
for (const [key, value] of entries) {
console.log(key, value);
}

TS2497

error TS2497: Module β€˜logdownβ€˜ resolves to a non-module entity and cannot be imported using this construct.

Broken Code ❌

Export: logdown.d.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
declare class Logdown {
constructor(options?: Object);
public debug(...args: any[]): void;
public error(...args: any[]): void;
public info(...args: any[]): void;
public log(...args: any[]): void;
public warn(...args: any[]): void;
public static disable(...args: string[]): void;
public static enable(...args: string[]): void;
}

declare module 'logdown' {
export = Logdown;
}

Import: app.ts

1
import {Logdown} from 'logdown';

Broken Code ❌ #2

Export

1
2
3
4
5
6
7
8
9
10
11
12
13
14
declare module 'logdown' {
class Logdown {
constructor(options?: Object);
public debug(...args: any[]): void;
public error(...args: any[]): void;
public info(...args: any[]): void;
public log(...args: any[]): void;
public warn(...args: any[]): void;
public static disable(...args: string[]): void;
public static enable(...args: string[]): void;
}

export = Logdown;
}

Import

1
2
3
import {Logdown} from "logdown";
...
this.logger = new Logdown({prefix: 'abc', alignOuput: true});

Note: TypeScript compiler option β€œallowSyntheticDefaultImports” must be set to true.

Import

1
import Logdown = require('logdown');

TS2498

error TS2498: Module 'node_modules/@types/ms/index'uses export = and cannot be used with export *

Broken Code ❌

index.ts

1
export * from 'ms';

Fixed Code βœ”οΈ

If a third-party module uses a default export (indicated by the export = syntax), you must use the default keyword to re-export this module:

1
export { default as ms } from 'ms';

TS2503

error TS2503: Cannot find namespace β€˜Reactβ€˜.

Broken Code ❌

1
export type CompositeComponent<P> = React.ComponentClass<P>;

Fixed Code βœ”οΈ

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.

1
2
3
import React from 'react';

export type CompositeComponent<P> = React.ComponentClass<P>;

error TS2503: Cannot find name β€˜process’. Do you need to install type definitions for node? Try npm i --save-dev @types/node.

Solution

Run yarn add --dev @types/node in your npm project.


TS2507

error TS2507: Type β€˜typeof EventEmitterβ€˜ is not a constructor function type.

Error happened when importing the exported class in another project.

Broken Code ❌

1
2
3
4
5
6
7
import EventEmitter from 'events';

export class WebSocketClient extends EventEmitter {
constructor() {
super();
}
}

Fixed Code βœ”οΈ

1
2
3
4
5
6
7
import {EventEmitter} from 'events';

export class WebSocketClient extends EventEmitter {
constructor() {
super();
}
}
Read more

TS2511

error TS2511: Cannot create an instance of an abstract class.

Broken Code ❌

1
2
3
myFunction = (strategyConstructor: typeof Strategy, config: StrategyConfig): Promise<Big> => {
// ....
};

Fixed Code βœ”οΈ

1
2
3
4
5
6
7
export interface Type<T> extends Function {
new (...args: any[]): T;
}

myFunction = (strategyConstructor: StrategyType<Strategy<StrategyConfig>>, config: StrategyConfig): Promise<Big> => {
// ....
};

Read more: Passing a class constructor as parameter to a function.


TS2512

error TS2512: Overload signatures must all be abstract or non-abstract.

Broken Code ❌

1
2
3
4
5
export abstract class MovingAverage {
update(prices: BigSource[]): Big | void;

abstract update(price: BigSource): Big | void;
}

Fixed Code βœ”οΈ

1
2
3
4
5
export abstract class MovingAverage {
abstract update(prices: BigSource[]): Big | void;

abstract update(price: BigSource): Big | void;
}

TS2515

error TS2515: Non-abstract class β€˜Dog’ does not implement inherited abstract member β€˜makeNoise’ from class β€˜Animal’.

Broken Code ❌

1
2
3
4
5
abstract class Animal {
abstract makeNoise(): string;
}

class Dog extends Animal {}

Fixed Code βœ”οΈ

If we derive a class from an abstract class, then we have to provide an implementation for all its abstract members:

1
2
3
4
5
6
7
8
9
abstract class Animal {
abstract makeNoise(): string;
}

class Dog extends Animal {
makeNoise(): string {
return 'Woof!';
}
}

Video Tutorial


TS2528

error TS2528: A module cannot have multiple default exports.

Broken Code ❌

1
2
3
4
5
const MyPerson = 'Benny';

export default MyPerson;

export default function MyPerson() {}

Fixed Code βœ”οΈ

Make sure to only have one default export:

1
2
3
const MyPerson = 'Benny';

export default MyPerson;

TS2531

error TS2531: Object is possibly β€˜null’.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
type Person = {
address: {
street: string;
zipCode: number;
} | null;
name: string;
};

function logStreet(person: Person): void {
console.log(person.address.street);
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
10
11
type Person = {
address: {
street: string;
zipCode: number;
} | null;
name: string;
};

function logStreet(person: Person): void {
console.log(person.address?.street);
}

TS2532

error TS2532: Object is possibly β€˜undefined’.

Broken Code ❌

1
2
3
4
5
6
7
type Person = {
age: number;
};

function logAge(person?: Person): void {
console.log(person.age);
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
type Person = {
age: number;
};

function logAge(person?: Person): void {
if (person) {
console.log(person.age);
}
}

Alternatively, we can use optional chaining:

1
2
3
4
5
6
7
type Person = {
age: number;
};

function logAge(person?: Person): void {
console.log(person?.age);
}

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.


TS2533

error TS2533: Object is possibly β€˜null’ or β€˜undefined’.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
type Person = {
address?: {
street: string;
zipCode: number;
} | null;
name: string;
};

function logStreet(person: Person): void {
console.log(person.address.street);
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
10
11
type Person = {
address?: {
street: string;
zipCode: number;
} | null;
name: string;
};

function logStreet(person: Person): void {
console.log(person.address?.street);
}

TS2536

error TS2536: Type string cannot be used to index type Config

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
export type StrategyConfig = {
[key: string]: string
};

export class GenericClass<Config extends StrategyConfig> {
public proxyConfig(
source: Config,
): Config {
return new Proxy<Config>(source, {
set: <ConfigKey extends keyof Config>(
config: Config,
property: string,
value: Config[ConfigKey],
) => {
config[property] = value;
return true;
},
});
}
}

Fixed Code βœ”οΈ

Because the type of property is a string and Config expects a ConfigKey, we need to ensure that our property is of type ConfigKey.

We can simply annotate the ConfigKey type to property, but we also have to make sure that ConfigKey extends the string type as the set method of a Proxy only accepts string | symbol:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
export type StrategyConfig = {
[key: string]: string
};

export class GenericClass<Config extends StrategyConfig> {
public proxyConfig(
source: Config,
): Config {
return new Proxy<Config>(source, {
set: <ConfigKey extends keyof Config & string>(
config: Config,
property: ConfigKey,
value: Config[ConfigKey],
) => {
config[property] = value;
return true;
},
});
}
}

TS2538

error TS2538: Type β€˜Person’ cannot be used as an index type.

Broken Code ❌

1
2
3
4
5
6
7
interface Person {
name: string;
}

function getValue(person: Person, key: Person): string {
return person[key];
}

Fixed Code βœ”οΈ

You cannot use an interface as an index type, but you can use all keys of the interface using the keyof type operator:

1
2
3
4
5
6
7
interface Person {
name: string;
}

function getValue(person: Person, key: keyof Person): string {
return person[key];
}

TS2539

error TS2539: Cannot assign to defaultName because it is not a variable.

Broken Code ❌

defaults.ts
1
export let defaultName = 'Benny';
main.ts
1
2
3
import {defaultName} from './defaults';

defaultName = 'Sofia';

Fixed Code βœ”οΈ

Using the let keyword might lead to the assumption of exporting a variable, but in reality, every export becomes a constant. As we’re aware, constants cannot be reassigned.

To work around this, we can use a little trick with how some types are handled. If we put our defaultName (initially a primitive string type) inside an object (which is a complex type), we can change the value inside the object as it is passed by reference:

defaults.ts
1
2
3
export const defaults = {
defaultName: 'Benny'
};
main.ts
1
2
3
import {defaults} from './defaults';

defaults.defaultName = 'Sofia';

TS2540

error TS2540: Cannot assign to β€˜nameβ€˜ because it is a read-only property.

Broken Code ❌

1
2
const user = {name: 'Benny'} as const;
user.name = 'Sofia';

Fixed Code βœ”οΈ

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:

1
2
const user = {name: 'Benny'};
user.name = 'Sofia';

TS2550

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.

Broken Code ❌

code.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
type HumanHero = typeof human & typeof hero;

const human = {
speak: () => {
}
};

const hero = {
fly: () => {
}
};

// Prototype-based inheritance
Object.setPrototypeOf(hero, human);
tsconfig.json
1
2
3
4
5
6
7
8
9
{
"compilerOptions": {
"lib": [
"dom",
"es5"
],
"target": "es6"
}
}

Fixed Code βœ”οΈ

ES5, also known as ECMAScript 2009, doesn’t include Object.setPrototypeOf which is why you have to upgrade to ES6 (also known as ES2015):

tsconfig.json
1
2
3
4
5
6
7
8
9
{
"compilerOptions": {
"lib": [
"dom",
"es6"
],
"target": "es6"
}
}

TS2551

error TS2551: Property β€˜titleβ€˜ does not exist on type β€˜Videoβ€˜. Did you mean β€˜titlesβ€˜?

Broken Code ❌

1
2
3
4
5
6
7
interface Video {
titles: string;
}

function showEpisode(this: Video, tag: string) {
console.log(`${this.title} - ${tag}`);
}

Fixed Code βœ”οΈ

There is a typo in our code which TypeScript’s compiler has caught for us. We have to rename the titles property:

1
2
3
4
5
6
7
interface Video {
title: string;
}

function showEpisode(this: Video, tag: string) {
console.log(`${this.title} - ${tag}`);
}

TS2552

error TS2552: Cannot find name β€˜readonlyArray’. Did you mean β€˜ReadonlyArray’?

Broken Code ❌

1
const array: readonlyArray<number> = [1, 2, 3];

Fixed Code βœ”οΈ

1
const array: ReadonlyArray<number> = [1, 2, 3];

TS2554

error TS2554: Expected 2 arguments, but got 1.

Broken Code ❌

1
2
3
4
5
function printName(firstName: string, lastName: string): void {
console.log(`${firstName} ${lastName}`);
}

printName('Michael');

Fixed Code βœ”οΈ

1
2
3
4
5
function printName(firstName: string, lastName: string): void {
console.log(`${firstName} ${lastName}`);
}

printName('Michael', 'Jordan');

Video Tutorial


TS2556

error TS2556: A spread argument must either have a tuple type or be passed to a rest parameter.

Broken Code ❌

1
2
3
4
5
function sum(a: number, b: number): number {
return a + b;
}

console.log(sum(1, ...[2, 3, 4, 5]));

Fixed Code βœ”οΈ

When calling a function using the spread syntax (...), we have to ensure that the called function uses a rest parameter:

1
2
3
4
5
function sum(a: number, ...b: number[]): number {
return a + b.reduce((c, d) => c + d);
}

console.log(sum(1, ...[2, 3, 4, 5]));

TS2558

error TS2558: Expected 2 type arguments, but got 1.

Broken Code ❌

1
2
3
4
5
function combine<X, Y>(a: X, b: Y): (X | Y)[] {
return [a, b];
}

combine<number>(1, '2');

Fixed Code βœ”οΈ

The combine function defines 2 type variables (X & Y), so you have to pass it 2 type arguments:

1
2
3
4
5
function combine<X, Y>(a: X, b: Y): (X | Y)[] {
return [a, b];
}

combine<number, string>(1, '2');

TS2559

error TS2559: Type β€˜{ city: string; }β€˜ has no properties in common with type β€˜Userβ€˜.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface User {
age?: number;
name?: string;
}

function increaseAge(user: User): void {
if (user.age) {
user.age += 1;
}
}

const user = {city: 'Berlin'};

increaseAge(user);

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface User {
age?: number;
name?: string;
}

function increaseAge(user: User): void {
if (user.age) {
user.age += 1;
}
}

const user = {age: 1, city: 'Berlin'};

increaseAge(user);

TS2564

error TS2564: Property β€˜name’ has no initializer and is not definitely assigned in the constructor.

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.

Broken Code ❌

1
2
3
class Dog {
private name: string;
}

Fixed Code βœ”οΈ

We have to initialize the name member either at its definition or within the constructor.

Solution 1:

1
2
3
class Dog {
private name: string = 'Laika';
}

Solution 2:

1
2
3
4
5
6
7
class Dog {
private name: string;

constructor() {
this.name = 'Laika';
}
}

Solution 3:

1
2
3
class Dog {
constructor(private name: string = 'Laika') {}
}

Video Tutorial


TS2567

error TS2567: Enum declarations can only merge with namespace or other enum declarations. lib.dom.d.ts(18299, 6): β€˜ResponseType’ was also declared here.

Broken Code ❌

1
2
3
4
enum ResponseType {
ACTIVE,
ERROR,
}

Fixed Code βœ”οΈ

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:

1
2
3
4
enum MyResponseType {
ACTIVE,
ERROR,
}

TS2571

error TS2571: Object is of type β€˜unknown’.

Broken Code ❌

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:

1
2
const x: unknown = 1337;
console.log(x.toString());

Fixed Code βœ”οΈ

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:

1
2
const x: number = 1337;
console.log(x.toString());

Broken Code ❌

1
2
3
export const hasUsers = (payload: unknown): payload is {users: string[]} => {
return 'users' in payload;
};

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
export const hasUsers = (payload: unknown): payload is {users: string[]} => {
if (payload && typeof payload === 'object') {
return 'users' in payload;
}
return false;
};

Alternative

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.


TS2574

error TS2574: A rest element type must be an array type.

Broken Code ❌

1
2
3
type Operation = '+' | '-';

type Calculation = [Operation, ...number];

Fixed Code βœ”οΈ

Simply turn ...number into ...number[]:

1
2
3
type Operation = '+' | '-';

type Calculation = [Operation, ...number[]];

TS2577

error TS2577: Return type annotation circularly references itself.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
13
type OurReply = ReturnType<typeof reply>;

function reply(text: string): OurReply {
if (text === 'Hello') {
return 'Hi!';
}

if (text === 'Goodbye') {
return 'Bye!';
}

return "What's up?";
}

Fixed Code βœ”οΈ

You can remove the circular reference by removing the explicit return type (OurReply) from the signature of your function:

1
2
3
4
5
6
7
8
9
10
11
12
13
type OurReply = ReturnType<typeof reply>;

function reply(text: string) {
if (text === "Hello") {
return "Hi!";
}

if (text === "Goodbye") {
return "Bye!";
}

return "What's up?";
}

TS2580

error TS2580: Cannot find name β€˜require’. Do you need to install type definitions for node? Try npm i --save-dev @types/node.

Broken Code ❌

1
2
const path = require('path');
console.log(path.basename(__dirname));

Fixed Code βœ”οΈ

Install typings for Node.js:

1
npm i --save-dev @types/node

Update code to modern import syntax:

1
2
import path from 'path';
console.log(path.basename(__dirname));

TS2582

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.

Broken Code ❌

1
2
3
test('create sum', () => {
expect(1 + 2).toBe(3);
});

Fixed Code βœ”οΈ

The error above is very specific to your testing framework and when using Jest it can be easily solved by installing definition files for Jest (npm i --save-dev @types/jest).

When you are using Playwright, then you would have to make sure that you properly import Playwright’s definition for test:

1
2
3
4
5
import {test, expect} from '@playwright/test';

test('create sum', () => {
expect(1 + 2).toBe(3);
});

TS2583

error TS2583: Cannot find name β€˜BigInt’. Do you need to change your target library? Try changing the β€˜lib’ compiler option to β€˜es2020’ or later.

Broken Code ❌

tsconfig.json
1
2
3
4
5
6
7
{
"compilerOptions": {
"lib": [
"dom"
]
}
}
ImmortalPerson.ts
1
2
3
type ImmortalPerson = {
age: BigInt;
}

Fixed Code βœ”οΈ

Arbitrary-precision integers (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:

tsconfig.json
1
2
3
4
5
6
7
8
{
"compilerOptions": {
"lib": [
"dom",
"es2020.bigint"
]
}
}

Alternatively, you can make all additional APIs from ES2020 available to your code:

tsconfig.json
1
2
3
4
5
6
7
8
{
"compilerOptions": {
"lib": [
"dom",
"es2020"
]
}
}

TS2584

error TS2584: Cannot find name β€˜console’. Do you need to change your target library? Try changing the β€˜lib’ compiler option to include β€˜dom’.

Broken Code ❌

TypeScript code:

1
console.log('Hello, World!');

TypeScript compiler configuration (tsconfig.json):

1
2
3
4
5
{
"compilerOptions": {
"lib": ["es2017"]
}
}

Fixed Code βœ”οΈ

You have to add the following to your β€œtsconfig.json” file:

1
2
3
4
5
{
"compilerOptions": {
"lib": ["es2017", "dom"]
}
}

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.


TS2588

error TS2588: Cannot assign to β€˜name’ because it is a constant.

Broken Code ❌

1
2
const name = 'Benny';
name = 'Sofia';

Fixed Code βœ”οΈ

You cannot reassign values to constants which is why you have to declare a variable using the let keyword:

1
2
let name = 'Benny';
name = 'Sofia';

TS2595

error TS2595: β€˜Reactβ€˜ can only be imported by using a default import.

Broken Code ❌

1
import {React} from 'react';

Fixed Code βœ”οΈ

A default import cannot be put in curly braces:

1
import React from 'react';

TS2611

error TS2611: β€˜nameβ€˜ is defined as a property in class β€˜Personβ€˜, but is overridden here in β€˜MyPersonβ€˜ as an accessor.

Broken Code ❌

1
2
3
4
5
6
7
8
9
abstract class Person {
name: string = 'unknown';
}

class MyPerson extends Person {
get name(): string {
return `${super.name.toUpperCase}`;
}
}

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:

1
2
3
4
5
6
7
8
9
abstract class Person {
accessor name: string = 'unknown';
}

class MyPerson extends Person {
get name(): string {
return `${super.name.toUpperCase}`;
}
}

TS2613

error TS2613: Module β€˜addβ€˜ has no default export. Did you mean to use β€˜import { add } from "add"β€˜ instead?

Broken Code ❌

add.ts
1
2
3
export function add(a: number, b: number): number {
return a + b;
}
main.ts
1
2
3
import add from './add';

console.log(add(1000, 337));

Fixed Code βœ”οΈ

To fix the bug we have to convert our named export into a default export:

add.ts
1
2
3
export default function add(a: number, b: number): number {
return a + b;
}

TS2614

TS2614: Module './add.js' has no exported member add. Did you mean to use import add from "./add.js" instead?

Broken Code ❌

add.ts

1
2
3
export default function add(a: number, b: number): number {
return a + b;
}

main.ts

1
import {add} from "./add.js";

Fixed Code βœ”οΈ

There are multiple ways to fix this. The simplest would be turning your import statement into a default import:

1
import add from "./add.js";

An alternative solution would be using a named export:

1
2
3
export function add(a: number, b: number): number {
return a + b;
}

You could actually use a named export and a default export in the same file:

1
2
3
4
5
6
7
export default function add(a: number, b: number): number {
return a + b;
}

export {
add
};

TS2616

error TS2616: β€˜React’ can only be imported by using β€˜import React = require(β€œreact”)’ or a default import.

Broken Code ❌

1
2
3
4
5
import {React, FC} from 'react';

const App: FC = (): JSX.Element => {
return <></>;
};

Fixed Code βœ”οΈ

Use default import for React:

1
2
3
4
5
import React, {FC} from 'react';

const App: FC = (): JSX.Element => {
return <></>;
};

TS2617

error TS2617: path can only be imported by using import path = require("node:path") or by turning on the esModuleInterop flag and using a default import.

Broken Code ❌

1
import { path } from "node:path";

Fixed Code βœ”οΈ

1
import path = require('node:path');

TS2632

error TS2632: Cannot assign to path because it is an import.

Broken Code ❌

1
2
3
import path from 'node:path';

path = {};

Fixed Code βœ”οΈ

1
const path = {};

TS2636

error TS2636: Type β€˜Func<super-T>β€˜ is not assignable to type β€˜Func<sub-T>β€˜ as implied by variance annotation. Type β€˜super-Tβ€˜ is not assignable to type β€˜sub-Tβ€˜.

Broken Code ❌

1
type Func<in T> = () => T;

Fixed Code βœ”οΈ

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:

1
type Func<out T> = () => T;

Alternatively, you can annotate it with both in and out (i.e. as invariant):

1
type Func<in out T> = () => T;

TS2637

error TS2637: Variance annotations are only supported in type aliases for object, function, constructor, and mapped types.

Broken Code ❌

1
type Pair<in T> = [T, T];

Fixed Code βœ”οΈ

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.

To resolve the error, simply remove the variance annotation.

1
type Pair<T> = [T, T];

TS2652

error TS2652: Merged declaration β€˜MyPersonβ€˜ cannot include a default export declaration. Consider adding a separate β€˜export default MyPersonβ€˜ declaration instead.

Broken Code ❌

1
2
3
4
5
const MyPerson = 'Benny';

export default function MyPerson() {
//
}

Fixed Code βœ”οΈ

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:

1
2
3
const MyPerson = 'Benny';

export default MyPerson;

TS2654

error TS2654: Exported external package typings file cannot contain tripleslash references. Please contact the package author to update the package definition.

Broken Code ❌

1
/// <reference path="../../../typings/index.d.ts" />

Fix

Video Tutorial


TS2656

error TS2656: Exported external package typings file β€˜../proteus.d.tsβ€˜ is not a module. Please contact the package author to update the package definition.

Broken Code ❌

proteus.d.ts
1
2
declare module Proteus {
}

Fixed Code βœ”οΈ

proteus.d.ts
1
2
export module Proteus {
}

TS2661

error TS2661: Cannot export β€˜getSdkβ€˜. Only local declarations can be exported from a module.

Broken Code ❌

index.ts
1
export {getSdk};
getSdk.ts
1
function getSdk() {}

Fixed Code βœ”οΈ

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:

index.ts
1
2
3
import {getSdk} from './getSdk';

export {getSdk};
getSdk.ts
1
export function getSdk() {}

TS2663

error TS2663: Cannot find name β€˜firstNameβ€˜. Did you mean the instance member β€˜this.firstNameβ€˜?

Broken Code ❌

1
2
3
4
5
class Person {
get firstName(): string {
return firstName;
}
}

Fixed Code βœ”οΈ

If you want to use a getter, you need to back it up with a private property:

1
2
3
4
5
6
7
class Person {
private _firstName: string = '';

get firstName(): string {
return this._firstName;
}
}

Starting from TypeScript 4.9, you can also use an auto-accessor field:

1
2
3
class Person {
accessor firstName: string = '';
}

TS2664

error TS2664: Invalid module name in augmentation, module β€˜gas-localβ€˜ cannot be found.

Broken Code ❌

main.ts
1
declare module "gas-local";

Fixed Code βœ”οΈ

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:

1
npm install gas-local --save

TS2665

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.

Broken Code ❌

main.ts
1
2
3
4
declare module "gas-local";
import gas from 'gas-local';

const glib = gas.require('./src');

Fixed Code βœ”οΈ

You have to move the shorthand ambient module declaration from a β€œ.ts” file into a β€œ.d.ts” file:

types.d.ts
1
declare module "gas-local";
main.ts
1
2
3
import gas from 'gas-local';

const glib = gas.require('./src');

TS2668

error TS2668: β€˜export’ modifier cannot be applied to ambient modules and module augmentations since they are always visible.

Info

Ambient modules

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.

Source: https://www.typescriptlang.org/docs/handbook/modules.html

Module Augmentation

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.

Source: https://blogs.msdn.microsoft.com/typescript/2016/02/22/announcing-typescript-1-8-2/

Broken Code ❌

1
2
3
export module 'amplify' {
export function publish(topic: string, ...args: any[]): boolean;
}

Fixed Code βœ”οΈ

1
export function publish(topic: string, ...args: any[]): boolean;

Usage

1
import amplify = require('amplify');

TS2669

error TS2669: Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.

Broken Code ❌

1
2
3
4
5
6
7
declare global {
namespace NodeJS {
interface Global {
__coverage__: {};
}
}
}

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:

Fixed Code βœ”οΈ

1
2
3
4
5
6
7
8
9
declare global {
namespace NodeJS {
interface Global {
__coverage__: {};
}
}
}

export {};

TS2677

error TS2677: A type predicate’s type must be assignable to its parameter’s type. Type β€˜numberβ€˜ is not assignable to type β€˜stringβ€˜.

Broken Code ❌

1
2
3
const isInteger = (input: string): input is number => {
return !!parseInt(input, 10);
};

Fixed Code βœ”οΈ

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:

1
2
3
const isInteger = (input: any): input is number => {
return !!parseInt(input, 10);
};

TS2678

error TS2678: Type β€˜StreamStatusβ€˜ is not comparable to type β€˜numberβ€˜.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
enum StreamStatus {
ONLINE = 'ONLINE',
OFFLINE = 'OFFLINE',
}

interface StreamResponse {
status: number;
}

function handleResponse(response: StreamResponse): void {
switch (response.status) {
case StreamStatus.ONLINE:
console.log('You are online.');
break;
case StreamStatus.OFFLINE:
console.log('You are offline.');
break;
}
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
enum StreamStatus {
ONLINE = 'ONLINE',
OFFLINE = 'OFFLINE',
}

interface StreamResponse {
status: StreamStatus;
}

function handleResponse(response: StreamResponse): void {
switch (response.status) {
case StreamStatus.ONLINE:
console.log('You are online.');
break;
case StreamStatus.OFFLINE:
console.log('You are offline.');
break;
}
}

TS2680

error TS2680: A β€˜this’ parameter must be the first parameter.

Broken Code ❌

1
2
3
4
5
6
7
type Person = {
name: string;
};

export function sayHello(text: string = 'Hello', this: Person): void {
console.log(`${text} ${this.name}`);
}

Fixed Code βœ”οΈ

TypeScript requires that a this parameter always comes first in the list of parameters:

1
2
3
4
5
6
7
type Person = {
name: string;
};

export function sayHello(this: Person, text: string = 'Hello'): void {
console.log(`${text} ${this.name}`);
}

TS2683

error TS2683: β€˜this’ implicitly has type β€˜any’ because it does not have a type annotation.

Broken Code ❌

1
2
3
export function sayHello(text: string = 'Hello'): void {
console.log(`${text} ${this.name}`);
}

Fixed Code βœ”οΈ

This bug is also a consequence of 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:

1
2
3
4
5
6
7
type Person = {
name: string;
};

export function sayHello(this: Person, text: string = 'Hello'): void {
console.log(`${text} ${this.name}`);
}

TS2684

error TS2684: The β€˜thisβ€˜ context of type β€˜voidβ€˜ is not assignable to method’s β€˜thisβ€˜ of type β€˜Personβ€˜.

Broken Code ❌

1
2
3
4
5
6
7
8
9
type Person = {
name: string;
};

export function sayHello(this: Person, text: string = 'Hello'): void {
console.log(`${text} ${this.name}`);
}

sayHello('Welcome');

Fixed Code βœ”οΈ

When calling a function that defines a this parameter, then we have to set the this context with apply, bind or call.

Using apply:

1
2
3
4
5
6
7
8
9
10
11
12
13
type Person = {
name: string;
};

export function sayHello(this: Person, text: string = 'Hello'): void {
console.log(`${text} ${this.name}`);
}

const benny: Person = {
name: 'Benny',
};

sayHello.apply(benny, ['Welcome']);

Using bind:

1
2
3
4
5
6
7
8
9
10
11
12
13
type Person = {
name: string;
};

export function sayHello(this: Person, text: string = 'Hello'): void {
console.log(`${text} ${this.name}`);
}

const benny: Person = {
name: 'Benny',
};

sayHello.bind(benny)('Welcome');

Using call:

1
2
3
4
5
6
7
8
9
10
11
12
13
type Person = {
name: string;
};

export function sayHello(this: Person, text: string = 'Hello'): void {
console.log(`${text} ${this.name}`);
}

const benny: Person = {
name: 'Benny',
};

sayHello.call(benny, 'Welcome');

Note: The TS2684 error may also occur when attempting to call static functions of a class with a private constructor.


TS2686

error TS2686: β€˜ko’ refers to a UMD global, but the current file is a module. Consider adding an import instead.

Broken Code ❌

1
const downloadProgress = ko.observable();

Fixed Code βœ”οΈ

1
2
3
import ko from 'knockout';

const downloadProgress = ko.observable();

error TS2686: β€˜sinon’ refers to a UMD global, but the current file is a module. Consider adding an import instead.

Broken Code ❌

1
2
import {SinonFakeServer} from 'sinon';
let server: SinonFakeServer;

Fixed Code βœ”οΈ

1
2
import * as sinon from 'sinon';
let server: sinon.SinonFakeServer;

error TS2686: β€˜React’ refers to a UMD global, but the current file is a module. Consider adding an import instead.

Broken Code ❌

1
2
3
4
5
import {FC} from 'react';

const App: FC = (): JSX.Element => {
return <></>;
};

Fixed Code βœ”οΈ

Use default import for React:

1
2
3
4
5
import React from 'react';

const App: React.FC = (): JSX.Element => {
return <></>;
};

TS2687

error TS2687: All declarations of β€˜status’ must have identical modifiers. lib.dom.d.ts(11620, 14): β€˜statusβ€˜ was also declared here.

Broken Code ❌

1
2
3
4
interface Response {
data?: string;
status: StreamStatus;
}

Fixed Code βœ”οΈ

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:

1
2
3
4
interface Response {
data?: string;
readonly status: number;
}

TS2689

error TS2689: Cannot extend an interface β€˜Animal’. Did you mean β€˜implements’?

Broken Code ❌

1
2
3
4
5
6
7
interface Animal {
name: string;
}

class Dog extends Animal {
name = 'Default Dog';
}

Fixed Code βœ”οΈ

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.

1
2
3
4
5
class Dog extends Animal {
protected makeNoise(): string {
return 'Woof!';
}
}

TS2691

error TS2691: An import path cannot end with a β€˜.d.ts’ extension. Consider importing β€˜./index’ instead.

Broken Code ❌

You cannot directly import code from declaration files:

1
import {myFunction} from './index.d.ts';

Fixed Code βœ”οΈ

You have to import functions from the source code file (e.g. index.ts):

1
import {myFunction} from './index';

TS2693

error TS2693: β€˜Candlestickβ€˜ only refers to a type, but is being used as a value here.

Broken Code ❌

main.ts

1
2
import Candlestick from '../../chart/Candlestick';
const candle = new Candlestick();

Candlestick.ts

1
2
3
4
5
6
7
8
interface Candlestick {
close: number;
high: number;
low: number;
open: number;
}

export default Candlestick;

Fixed Code βœ”οΈ

main.ts

1
2
import Candlestick from '../../chart/Candlestick';
const candle = new Candlestick();

Candlestick.ts

1
2
3
4
5
6
7
8
class Candlestick {
close: number = 0;
high: number = 0;
low: number = 0;
open: number = 0;
}

export default Candlestick;

TS2694

error TS2694: Namespace β€˜Reactβ€˜ has no exported member β€˜NonExistentβ€˜.

Broken Code ❌

1
2
3
import React from 'react';

export type CompositeComponent<P> = React.NonExistent<P>;

Fixed Code βœ”οΈ

When trying to import a type that is missing in an external namespace, then you have to add the missing typings yourself:

1
2
3
4
5
6
7
8
9
import React from 'react';

declare global {
namespace React {
type NonExistent<P> = React.FunctionComponent<P>;
}
}

export type CompositeComponent<P> = React.NonExistent<P>;

TS2695

error TS2695: Left side of comma operator is unused and has no side effects.

Broken Code ❌

1
2
3
4
5
6
7
8
import express from 'express';

const app = express();

app.use((, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});

Fixed Code βœ”οΈ

You just cannot leave out a callback parameter if you don’t want to use it. Mark it with an underscore (_) instead:

1
2
3
4
5
6
7
8
import express from 'express';

const app = express();

app.use((_, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});

TS2706

error TS2706: Required type parameters may not follow optional type parameters.

Broken Code ❌

1
2
3
4
5
6
class KeyValuePair<Key = string, Value> {
key: Key | undefined;
value: Value | undefined;
}

const populationFigures = new KeyValuePair<string, number>();

Fixed Code βœ”οΈ

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.

To solve the situation, we have can switch the position of the two parameters which would impact how we use the code:

1
2
3
4
5
6
class KeyValuePair<Value, Key = string> {
key: Key | undefined;
value: Value | undefined;
}

const populationFigures = new KeyValuePair<number, string>();

Alternatively, we can also set a default type for Value:

1
2
3
4
5
6
class KeyValuePair<Key = string, Value = string> {
key: Key | undefined;
value: Value | undefined;
}

const populationFigures = new KeyValuePair<string, number>();

TS2709

error TS2709: Cannot use namespace β€˜globalThisβ€˜ as a type.

Broken Code ❌

1
2
3
4
5
function parseNumber(this: globalThis, input: string): number {
return this.parseInt(input);
}

parseNumber.call(this, '100');

Fixed Code βœ”οΈ

You cannot use a namespace as a type, but you can get the type assigned with that namespace by using the typeof operator:

1
2
3
4
5
function parseNumber(this: typeof globalThis, input: string): number {
return this.parseInt(input);
}

parseNumber.call(this, '100');

TS2713

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"]β€˜?

Broken Code ❌

1
2
3
4
5
6
7
8
type CheckSuite = {
passed: boolean
status: 'ok' | 'error'
}

type ServerResponse = {
status: CheckSuite.status
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
type CheckSuite = {
passed: boolean
status: 'ok' | 'error'
}

type ServerResponse = {
status: Pick<CheckSuite, 'status'>
}

TS2715

error TS2715: Abstract property β€˜name’ in class β€˜Animal’ cannot be accessed in the constructor.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
abstract class Animal {
abstract name: string;
}

class Dog extends Animal {
constructor(name: string) {
super();
this.name = name;
}
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
10
11
12
abstract class Animal {
abstract name: string;
}

class Dog extends Animal {
public name;

constructor(name: string) {
super();
this.name = name;
}
}

TS2717

error TS2717: Subsequent property declarations must have the same type. Property β€˜verboseβ€˜ must be of type β€˜booleanβ€˜, but here has type β€˜stringβ€˜.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
declare namespace GreetingLib {
interface LogOptions {
verbose: boolean;
}
}

declare namespace GreetingLib {
interface LogOptions {
verbose: string;
}
}

Fixed Code βœ”οΈ

When declaring a property (in this case verbose) twice, then the second declaration must follow the typings of the first declaration:

1
2
3
4
5
6
7
8
9
10
11
declare namespace GreetingLib {
interface LogOptions {
verbose: boolean;
}
}

declare namespace GreetingLib {
interface LogOptions {
verbose: boolean;
}
}

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.

Video Tutorial


TS2720

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β€˜.

Broken Code ❌

1
2
3
4
5
6
7
8
9
abstract class Animal {
protected abstract makeNoise(): string;
}

class Dog implements Animal {
protected makeNoise(): string {
return 'Woof!';
}
}

Fixed Code βœ”οΈ

The implements keyword is reserved to implement interfaces. If you want to work with class inheritance, you have to use extends:

1
2
3
4
5
6
7
8
9
abstract class Animal {
protected abstract makeNoise(): string;
}

class Dog extends Animal {
protected makeNoise(): string {
return 'Woof!';
}
}

Video Tutorial


TS2722

error TS2722: Cannot invoke an object which is possibly β€˜undefinedβ€˜.

Broken Code ❌

1
2
3
4
5
function handleClick(event: {
onClick?: () => {}
}): void {
event.onClick();
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
function handleClick(event: {
onClick?: () => {}
}): void {
if (event.onClick) {
event.onClick();
}
}

As of TypeScript 3.7 you can also use the optional chaining (?.) operator to call a method on an object if it exists:

1
2
3
4
5
function handleClick(event: {
onClick?: () => {}
}): void {
event.onClick?.();
}

A third possibility is to use reference validation:

1
2
3
4
5
function handleClick(event: {
onClick?: () => {}
}): void {
event.onClick && event.onClick();
}

TS2724

error TS2724: β€˜./indexβ€˜ has no exported member named β€˜HeaderOptionsβ€˜. Did you mean β€˜HeaderOptionβ€˜?

Broken Code ❌

index.ts
1
2
3
4
export interface HeaderOption {
Authorization: string;
'Cache-Control': string;
}
printHeader.ts
1
2
3
4
5
import {HeaderOptions} from './index';

export function printHeader(header: HeaderOptions) {
console.log(header);
}

Fixed Code βœ”οΈ

TypeScript noticed a typing error in the name of the imported interface. The code will work if we correct the typo:

printHeader.ts
1
2
3
4
5
import {HeaderOption} from './index';

export function printHeader(header: HeaderOption) {
console.log(header);
}

TS2730

error TS2730: An arrow function cannot have a β€˜this’ parameter.

Broken Code ❌

1
2
3
const loadInitialData = (this: Highcharts.Chart): void => {
// ...
};

Fixed Code βœ”οΈ

You have to turn the arrow function expression into to a function declaration:

1
2
3
function loadInitialData(this: Highcharts.Chart): void {
// ...
}

TS2732

error TS2732: Cannot find module β€˜../../package.json’. Consider using β€˜β€“resolveJsonModule’ to import module with β€˜.json’ extension.

Broken Code ❌

1
import pkg from '../../package.json';

Fixed Code βœ”οΈ

To fix the issue and allow importing JSON files, you have to set β€œresolveJsonModule” to true in your β€œtsconfig.json” file.


TS2739

error TS2739: Type β€˜{}β€˜ is missing the following properties from type β€˜Personβ€˜: age, name

Broken Code ❌

1
2
3
4
5
6
type Person = {
age: number;
name: string;
};

const benny: Person = {};

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
type Person = {
age: number;
name: string;
};

const benny: Person = {
age: 34,
name: 'Benny',
};

Video Tutorial

error TS2739: Type β€˜string[]’ is missing the following properties from type β€˜Promise β€˜: then, catch, [Symbol.toStringTag]

Broken Code ❌

1
2
3
function myTest(): Promise<string[]> {
return [''];
}

When your function specifies to return a Promise, you have to ensure that your return value is also wrapped in a Promise:

1
2
3
function myTest(): Promise<string[]> {
return Promise.resolve(['']);
}

Alternatively, you can make use of the async keyword, which will automatically wrap your return value into a Promise:

1
2
3
async function myTest(): Promise<string[]> {
return [''];
}

TS2740

error TS2740: Type β€˜TextLineβ€˜ is missing the following properties from type β€˜Positionβ€˜: line, character, isBefore, isBeforeOrEqual, and 6 more.

Broken Code ❌

1
2
3
4
5
import {Position, TextEditor} from 'vscode';

function logPosition(textEditor: TextEditor, startLine: Position = textEditor.document.lineAt(0)) {
console.log(startLine.line);
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
import {Position, TextEditor} from 'vscode';

function logPosition(textEditor: TextEditor, startLine: Position = textEditor.document.lineAt(0).range.start) {
console.log(startLine.line);
}

TS2741

error TS2741: Property β€˜name’ is missing in type β€˜{}’ but required in type β€˜Animal’.

Broken Code ❌

1
2
3
4
5
interface Animal {
name: string;
}

const laika: Animal = {};

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
interface Animal {
name: string;
}

const laika: Animal = {
name: 'Laika',
};

Video Tutorial


TS2742

error TS2742: The inferred type of β€˜ProductDeleteDocumentβ€˜ cannot be named without a reference to β€˜graphql-tag/node_modules/graphql/language/astβ€˜. This is likely not portable. A type annotation is necessary.

Broken Code ❌

1
2
3
4
5
6
7
export const ProductDeleteDocument = gql`
mutation ProductDelete($productId: ID!) {
productDelete(input: { id: $productId }) {
deletedProductId
}
}
`;

Fixed Code βœ”οΈ

TypeScript asks for a type annotation to explicitly resolve the inferred type, so let’s add a type annotation:

1
2
3
4
5
6
7
8
9
import {DocumentNode} from 'graphql';

export const ProductDeleteDocument: DocumentNode = gql`
mutation ProductDelete($productId: ID!) {
productDelete(input: { id: $productId }) {
deletedProductId
}
}
`;

In a monorepository the error TS2742 can show up when you are using a package that has not set a β€œmain” property in its β€œpackage.json” file. Sometimes it also happens that there is a β€œtypes” property which does not point to the correct typings. Make sure both paths are present and relative:

package.json
1
2
3
4
{
"main": "./dist/index.js",
"types": "./dist/index.d.ts"
}

You can run into this error when a code generator, such as graphql-code-generator, misses to render an important statement (see here). This can happen when the generator relies on implicit typings (type inference) and it can be fixed by instructing your code generator to render the missing import statement. Depending on your code generator this could be done through a config file:

1
2
3
4
5
6
plugins:
- add:
content: 'import type { DocumentNode } from "graphql/language/ast";'
- typescript
- typescript-operations
- typescript-react-apollo

TS2749

error TS2749: β€˜paramNamesβ€˜ refers to a value, but is being used as a type here. Did you mean β€˜typeof paramNamesβ€˜?

Broken Code ❌

1
2
3
4
5
6
7
8
const paramNames = ['age', 'name'];

const person: {
[param in paramNames]: string;
} = {
age: '34',
name: 'Benny',
};

Fixed Code βœ”οΈ

1
2
3
4
5
6
7
8
type paramNames = 'age' | 'name';

const person: {
[param in paramNames]: string;
} = {
age: '34',
name: 'Benny',
};

TS2769

error TS2769: No overload matches this call.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
function sum(a: number, b: number): number;
function sum(a: string, b: string): string;
function sum(a: number | string, b: number | string): number | string {
if (typeof a === 'number' && typeof b === 'number') {
return a + b;
}
return `${parseInt(a + '', 10) + parseInt(b + '', 10)}`;
}

const result = sum('1000', 337);

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Function Overload Signature 1
function sum(a: number, b: number): number;
// Function Overload Signature 2
function sum(a: string, b: string): string;
// Function Overload Signature 3
function sum(a: string, b: number): string;
function sum(a: number | string, b: number | string): number | string {
if (typeof a === 'number' && typeof b === 'number') {
return a + b;
}
return `${parseInt(a + '', 10) + parseInt(b + '', 10)}`;
}

const result = sum('1000', 337);

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 of number | string:

1
2
3
4
5
6
7
8
function sum(a: number | string, b: number | string): number | string {
if (typeof a === 'number' && typeof b === 'number') {
return a + b;
}
return `${parseInt(a + '', 10) + parseInt(b + '', 10)}`;
}

const result = sum('1000', 337);

TS2774

error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
13
interface MyDog {
age: () => number;
}

interface MyPerson {
name: string;
age: () => number;
}

function printAge(user: MyPerson | MyDog): void {
if (user.age) {
}
}

Fixed Code βœ”οΈ

Both interfaces (MyPerson & MyDog) declare a function named age, so that if-condition to check for its existence is unnecessary:

1
2
3
4
5
6
7
8
9
10
11
12
interface MyDog {
age: () => number;
}

interface MyPerson {
name: string;
age: () => number;
}

function printAge(user: MyPerson | MyDog): void {
console.log(user.age());
}

TS2779

error TS2779: The left-hand side of an assignment expression may not be an optional property access.

Broken Code ❌

1
2
3
4
5
6
type User = {
id: number;
name: string;
};
const someUsers: Map<string, User> = new Map();
someUsers.get('some-user-id')?.name = 'Benny';

Fixed Code βœ”οΈ

You cannot assign a value to a property which might be undefined. As Map.get() may return undefined, you have to add an existence check:

1
2
3
4
5
6
7
8
9
type User = {
id: number;
name: string;
}
const someUsers: Map<string, User> = new Map();
const user = someUsers.get('some-user-id');
if (user) {
user.name = 'Benny';
}

TS2786

error TS2786: β€˜Componentβ€˜ cannot be used as a JSX component.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
13
import type {NextPage} from 'next';
import type {AppProps} from 'next/app';

type AppPropsWithLayout = AppProps & {
Component: NextPage & {
getLayout?: (page: React.ReactElement) => React.ReactNode;
};
};

export default function AdvisoryApp({Component, pageProps}: AppPropsWithLayout): JSX.Element {
const getLayout = Component.getLayout ?? (page => page);
return <>{getLayout(<Component {...pageProps} />)}</>;
}

Fixed Code βœ”οΈ

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.

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).


TS2790

error TS2790: The operand of a β€˜delete’ operator must be optional.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
interface User {
age: number;
name: string;
}

const benny: User = {
age: 35,
name: 'Benny'
};

delete benny.age;

Fixed Code βœ”οΈ

When using the delete operator to remove a property from an object, the property must be defined as optional in TypeScript:

1
2
3
4
5
6
7
8
9
10
11
interface User {
age?: number;
name: string;
}

const benny: User = {
age: 35,
name: 'Benny'
};

delete benny.age;

TS2792

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?

Broken Code ❌

playwright.config.staging.ts
1
2
3
4
5
6
7
8
9
import { PlaywrightTestConfig } from '@playwright/test';

const config: PlaywrightTestConfig = {
use: {
baseURL: 'https://my-staging-environment.com/',
},
};

export default config;
tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"moduleResolution": "classic"
}
}

Fixed Code βœ”οΈ

To fix the problem you have to use "moduleResolution": "node" in your TS config:

tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"moduleResolution": "node"
}
}

TS2794

error TS2794: Expected 1 arguments, but got 0. Did you forget to include β€˜voidβ€˜ in your type argument to β€˜Promiseβ€˜?

Broken Code ❌

1
2
3
await new Promise((resolve, reject) => {
resolve();
});

Fixed Code βœ”οΈ

When a Promise resolves with nothing, you need to define that as a type argument to the generic Promise:

1
2
3
await new Promise<void>((resolve, reject) => {
resolve();
});

TS2802

error TS2802: Type β€˜Set<string>β€˜ can only be iterated through when using the β€˜β€“downlevelIteration’ flag or with a β€˜β€“target’ of β€˜es2015’ or higher.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
const data = [
{
code: 'DEU',
country: 'Germany',
},
{
code: 'MAR',
country: 'Morocco',
},
];

const countries = [...new Set(data.map(item => item.country))];
1
2
3
4
5
6
7
8
9
{
"compilerOptions": {
"lib": ["dom", "es5"],
"outDir": "dist",
"rootDir": "src",
"strict": true,
"target": "es5"
}
}

Fixed Code βœ”οΈ

In order to resolve the issue, you need to use a higher target environment that is more recent than ES5, such as ES6 for example:

1
2
3
4
5
6
7
8
9
{
"compilerOptions": {
"lib": ["dom", "es5"],
"outDir": "dist",
"rootDir": "src",
"strict": true,
"target": "es6"
}
}

Alternative:

TypeScript will downlevel your code based on your defined β€œtarget” to support older JavaScript runtimes that lack built-in iterables. You can enable the downlevelIteration option to ensure compatibility with both legacy and modern platforms. This option generates a helper function that checks if the modern iteration is possible. If it is not supported, the helper function falls back to a legacy iteration, such as index-based iteration.

1
2
3
4
5
6
7
8
9
10
{
"compilerOptions": {
"downlevelIteration": true,
"lib": ["dom", "es5"],
"outDir": "dist",
"rootDir": "src",
"strict": true,
"target": "es5"
}
}

TS2813

error TS2813: Class declaration cannot implement overload list for β€˜MyClass’.

Broken Code ❌

1
2
3
class MyClass {}

function MyClass(): void {}

Function declarations get hoisted, so you cannot give your class the name of your function. Renaming your class solves the issue:

Fixed Code βœ”οΈ

1
2
3
class MyClassWithAnotherName {}

function MyClass(): void {}

TS2814

error TS2814: Function with bodies can only merge with classes that are ambient.

Solution

Broken Code ❌

1
2
3
class MyClass {}

function MyClass(): void {}

Your function cannot be named after your class, so you will have to rename your function:

Fixed Code βœ”οΈ

1
2
3
class MyClass {}

function MyFunctionWithAnotherName(): void {}

Alternatively you can declare an ambient class which gets implemented by your function:

1
2
3
declare class MyClass {}

function MyClass(): void {}

TS4020

error TS4020: β€˜extends’ clause of exported class β€˜StrategyPOJOβ€˜ has or is using private name β€˜Modelβ€˜.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
const {Model} = require('objection');

class StrategyPOJO extends Model {
static tableName = 'strategies';
config: string | undefined;
exchange: string | undefined;
identifier: string | undefined;
symbol: string | undefined;
}

export {StrategyPOJO};

Fixed Code βœ”οΈ

1
2
3
4
5
6
7
8
9
10
11
import {Model} from 'objection';

class StrategyPOJO extends Model {
static tableName = 'strategies';
config: string | undefined;
exchange: string | undefined;
identifier: string | undefined;
symbol: string | undefined;
}

export {StrategyPOJO};

TS4025

error TS4025: Exported variable β€˜Appβ€˜ has or is using private name β€˜FCβ€˜.

Broken Code ❌

1
2
3
4
5
import React from 'react';

const App: FC = (): JSX.Element => {
return <></>;
};

Fixed Code βœ”οΈ

When using an external type (like FC) you also have to make sure that it is imported:

1
2
3
4
5
import React, {FC} from 'react';

const App: FC = (): JSX.Element => {
return <></>;
};

TS4060

error TS4060: Return type of exported function has or is using private name β€˜JSX’.

Broken Code ❌

1
2
3
4
5
function App(): JSX.Element {
return <p>My App!</p>;
}

export default App;

Fixed Code βœ”οΈ

The global JSX namespace is declared in @types/react. You have to install the @types/react package to make use of it:

1
yarn add --dev @types/react

TS4063

error TS4063: Parameter β€˜configβ€˜ of constructor from exported class has or is using private name β€˜DoubleMovingAverageConfigβ€˜.

Broken Code ❌

1
2
3
4
5
6
7
8
9
type DoubleMovingAverageConfig = {
lastBuyPrice: string;
lastSellPrice: string;
warmUpCandles: number;
};

class DoubleMovingAverage extends Strategy {
constructor(private setup: StrategySetup, private config?: DoubleMovingAverageConfig) {}
}

Fixed Code βœ”οΈ

1
2
3
4
5
6
7
8
9
export type DoubleMovingAverageConfig = {
lastBuyPrice: string;
lastSellPrice: string;
warmUpCandles: number;
};

class DoubleMovingAverage extends Strategy {
constructor(private setup: StrategySetup, private config?: DoubleMovingAverageConfig) {}
}

TS4075

error TS4075: Parameter β€˜event’ of method from exported interface has or is using private name β€˜Strategy’.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
export interface Strategy<SpecificConfig extends StrategyConfig> {
on(event: Strategy.TOPIC.TRADER_DELETE, listener: () => void): this;
}

export abstract class Strategy<SpecificConfig extends StrategyConfig> extends EventEmitter {
static readonly TOPIC = {
TRADER_DELETE: 'TRADER_DELETE',
};

// ...
}

Fixed Code βœ”οΈ

1
2
3
4
5
6
7
8
9
10
11
12
13
enum TOPIC {
TRADER_DELETE = 'TRADER_DELETE',
}

export interface Strategy<SpecificConfig extends StrategyConfig> {
on(event: TOPIC.TRADER_DELETE, listener: () => void): this;
}

export abstract class Strategy<SpecificConfig extends StrategyConfig> extends EventEmitter {
static readonly TOPIC = TOPIC;

// ...
}

TS4081

error TS4081: Exported type alias β€˜MyReturnTypeβ€˜ has or is using private name β€˜getSdkβ€˜.

Broken Code ❌

index.ts
1
export type MyReturnType = ReturnType<typeof getSdk>;
getSdk.ts
1
function getSdk() {}

Fixed Code βœ”οΈ

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:

index.ts
1
2
3
import {getSdk} from './getSdk';

export type MyReturnType = ReturnType<typeof getSdk>;
getSdk.ts
1
export function getSdk() {}

TS4104

error TS4104: The type β€˜readonly [1, 2, 3]β€˜ is β€˜readonly’ and cannot be assigned to the mutable type β€˜[1, 2, 3]β€˜.

Broken Code ❌

1
const array: [1, 2, 3] = [1, 2, 3] as const;

Fixed Code βœ”οΈ

Using a const assertion makes your array immutable, so you have to use the readonly modifier for its type:

1
const array: readonly [1, 2, 3] = [1, 2, 3] as const;

Alternative:

1
const array: Readonly<[1, 2, 3]> = [1, 2, 3] as const;

Alternative #2:

1
const array: ReadonlyArray<number> = [1, 2, 3] as const;

TS4112

error TS4112: This member cannot have an β€˜override’ modifier because its containing class does not extend another class.

Broken Code ❌

1
2
3
4
5
class Cat {
override makeNoise(): string {
return 'Meow!';
}
}

Fixed Code βœ”οΈ

1
2
3
4
5
class Cat {
makeNoise(): string {
return 'Meow!';
}
}

TS4113

error TS4113: This member cannot have an β€˜overrideβ€˜ modifier because it is not declared in the base class β€˜MyBaseClassβ€˜.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
class MyBaseClass {
sayHello(): string {
return 'Hello!';
}
}

class MyDerivedClass extends MyBaseClass {
override sayWelcome(): string {
return 'Welcome!';
}
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
9
10
11
class MyBaseClass {
sayHello(): string {
return 'Hello!';
}
}

class MyDerivedClass extends MyBaseClass {
override sayHello(): string {
return 'Welcome!';
}
}

Depending on our use case, we can also remove the override modifier:

1
2
3
4
5
6
7
8
9
10
11
class MyBaseClass {
sayHello(): string {
return 'Hello!';
}
}

class MyDerivedClass extends MyBaseClass {
sayWelcome(): string {
return 'Welcome!';
}
}

TS4114

error TS4114: This member must have an β€˜overrideβ€˜ modifier because it overrides a member in the base class β€˜MyBaseClassβ€˜.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
class MyBaseClass {
sayHello(): string {
return 'Hello!';
}
}

class MyDerivedClass extends MyBaseClass {
sayHello(): string {
return 'Welcome!';
}
}

Fixed Code βœ”οΈ

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):

1
2
3
4
5
6
7
8
9
10
11
class MyBaseClass {
sayHello(): string {
return 'Hello!';
}
}

class MyDerivedClass extends MyBaseClass {
override sayHello(): string {
return 'Welcome!';
}
}

TS5023

error TS5023: Unknown compiler option β€˜-cβ€˜.

Broken Code ❌

1
npx tsc -c mytsconfig.json

Fixed Code βœ”οΈ

If you want to point the TypeScript compiler to a different configuration, you have to use the --project flag (see all tsc CLI options):

1
npx tsc --project mytsconfig.json

TS5024

error TS5024: Compiler option β€˜lib’ requires a value of type string.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
{
"compilerOptions": {
"lib": [6],
"module": "commonjs",
"moduleResolution": "node",
"outDir": "dist",
"rootDir": "src",
"target": "es6"
}
}

Fixed Code βœ”οΈ

You have to define a valid set of high level libraries (such as β€œes6”) that are available in your runtime:

1
2
3
4
5
6
7
8
9
10
{
"compilerOptions": {
"lib": ["es6"],
"module": "commonjs",
"moduleResolution": "node",
"outDir": "dist",
"rootDir": "src",
"target": "es6"
}
}

TS5025

error TS5025: Unknown compiler option β€˜β€“no-emit’. Did you mean β€˜noEmit’?

Broken Code ❌

1
tsc --no-emit

Fixed Code βœ”οΈ

Use camel case writing:

1
tsc --noEmit

TS5042

error TS5042: Option β€˜project’ cannot be mixed with source files on a command line.

Broken Code ❌

1
npx tsc -p tsconfig.strict.json src/main.ts

Fixed Code βœ”οΈ

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:

tsconfig.strict.json
1
2
3
4
5
6
7
8
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"outDir": "dist"
},
"extends": "@tstv/tsconfig-common/tsconfig.json",
"include": ["src/main.ts"]
}

TS5054

error TS5054: A β€˜tsconfig.json’ file is already defined at: β€˜C:/dev/bennycode/ts-node-starter/tsconfig.jsonβ€˜.

Broken Code ❌

1
npx tsc --init

Fixed Code βœ”οΈ

You cannot initialize a new TypeScript compiler configuration when there is one already present. You have to delete the existing file first.


TS5055

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.

Broken Code ❌

1
tsc mycode.js --allowJs

Fixed Code βœ”οΈ

1
tsc mycode.js --allowJs --outDir dist

Alternatively, you can also skip compiling code (if you just want to check the types of your code):

1
tsc mycode.js --allowJs --noEmit

TS5058

error TS5058: The specified path does not exist: β€˜test.json’.

Broken Code ❌

1
npx tsc --project test.json

Fixed Code βœ”οΈ

You probably don’t have a TS config named test.json. Try to load tsconfig.json:

1
npx tsc --project tsconfig.json

TS5069

error TS5069: Option β€˜declarationMap’ cannot be specified without specifying option β€˜declaration’ or option β€˜composite’.

Broken Code ❌

tsconfig.json
1
2
3
4
5
6
{
"compilerOptions": {
"declaration": false,
"declarationMap": true
}
}

Fixed Code βœ”οΈ

You have to activate the β€œdeclaration” property before you can activate β€œdeclarationMap”:

tsconfig.json
1
2
3
4
5
6
{
"compilerOptions": {
"declaration": true,
"declarationMap": true
}
}

TS5070

error TS5070: Option β€˜β€“resolveJsonModule’ cannot be specified without β€˜node’ module resolution strategy.

Broken Code ❌

1
2
3
4
5
6
7
8
9
{
"compilerOptions": {
"jsx": "preserve",
"lib": ["dom", "dom.iterable", "esnext"],
"module": "esnext",
"resolveJsonModule": true,
"target": "es6"
}
}

Fixed Code βœ”οΈ

Just define the β€œmoduleResolution” property and set it to β€œnode”:

tsconfig.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"compilerOptions": {
"jsx": "preserve",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"target": "es6"
}
}

TS5083

error TS5083: Cannot read file β€˜base.jsonβ€˜.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
{
"extends": "./base.json",
"compilerOptions": {
"lib": ["dom", "es6"],
"module": "commonjs",
"moduleResolution": "node",
"outDir": "dist",
"rootDir": "src",
"target": "es6"
}
}

Fixed Code βœ”οΈ

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.


TS5087

error TS5087: A labeled tuple element is declared as rest with a β€˜...β€˜ before the name, rather than before the type.

Broken Code ❌

1
2
3
type Operation = "+" | "-";

type CalcInput = [operation: Operation, numbers: ...number[]];

Fixed Code βœ”οΈ

We have to move the rest operator to the label name:

1
type CalcInput = [operation: Operation, ...numbers: number[]];

TS5101

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.

tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"importsNotUsedAsValues": "error"
}
}

Fixed Code βœ”οΈ

The compiler option importsNotUsedAsValues is not recommended when using TypeScript 5 and above, so you have to remove it from your tsconfig.json file:

tsconfig.json
1
2
3
4
{
"compilerOptions": {
}
}

TS6053

error TS6053: File β€˜/typings/index.d.tsβ€˜ not found.

Broken Code ❌

1
/// <reference path='/typings/index.d.ts' />

Fixed Code βœ”οΈ

Use relative paths when using Triple-Slash Directives:

1
/// <reference path='../../../typings/index.d.ts' />

Read more: 8 Steps to Migrating from JavaScript to TypeScript


TS6059

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.

Broken Code ❌

1
import pkg from '../../../../package.json';

Fixed Code βœ”οΈ

When using require then we can access files outside the specified root folder for input files (β€œrootDir” in β€œtsconfig.json”):

1
const pkg = require('../../../../package.json');

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”.


TS6133

error TS6133: β€˜volumeβ€˜ is declared but its value is never read.

Broken Code ❌

test.ts
1
const closes = ohlc.map(([time, open, high, low, close, volume]) => (close));
tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"noUnusedParameters": true
}
}

Fixed Code βœ”οΈ

tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"noUnusedParameters": false
}
}

error TS6133: β€˜bβ€˜ is declared but its value is never read.

Broken Code ❌

test.ts
1
let b;
tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"noUnusedLocals": true
}
}

Fixed Code βœ”οΈ

You can remove the unused variable from your code or disable the check for unused variables in your TypeScript compiler config:

tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"noUnusedLocals": false
}
}

Video Tutorial


TS6138

error TS6138: Property β€˜lastNameβ€˜ is declared but its value is never read.

Broken Code ❌

User.ts
1
2
3
4
5
6
7
8
class User {
constructor(private firstName: string, private lastName: string) {
}

get fullName() {
return this.firstName;
}
}

Fixed Code βœ”οΈ

Simply make use of the lastName property:

User.ts
1
2
3
4
5
6
7
8
class User {
constructor(private firstName: string, private lastName: string) {
}

get fullName() {
return `${this.firstName} ${this.lastName}`;
}
}

TS6192

error TS6192: All imports in import declaration are unused.

Broken Code ❌

1
2
3
import {type BigSource, Big} from 'big.js';

console.log('Not using big.js API');

Fixed Code βœ”οΈ

When multiple imports from a package are not being used, you will receive error TS6192. You can easily fix it by removing the unused import statement:

1
console.log('Not using big.js API');

TS6196

error TS6196: β€˜MyAbstractClassβ€˜ is declared but never used.

Broken Code ❌

1
2
3
abstract class MyAbstractClass {
abstract getResult(): boolean;
}

Fixed Code βœ”οΈ

You have three possibilities to fix the broken code:

  1. Make use of MyAbstractClass in your application
  2. Export MyAbstractClass
  3. Set β€œnoUnusedLocals” to false in your β€œtsconfig.json”
1
2
3
export abstract class MyAbstractClass {
abstract getResult(): boolean;
}

TS6198

error TS6198: All destructured elements are unused.

Broken Code ❌

1
2
3
4
5
6
7
8
function returnSomething(): {low: number; high: number} {
return {
low: 10,
high: 20,
};
}

const {low: lowest, high: highest} = returnSomething();

Fixed Code βœ”οΈ

You have to make use of the destructured values in your application / code:

1
2
3
4
5
6
7
8
9
10
function returnSomething(): {low: number; high: number} {
return {
low: 10,
high: 20,
};
}

const {low: lowest, high: highest} = returnSomething();

console.log(lowest + highest);

TS6504

error TS6504: File β€˜mycode.jsβ€˜ is a JavaScript file. Did you mean to enable the β€˜allowJsβ€˜ option?

Broken Code ❌

1
tsc mycode.js

Fixed Code βœ”οΈ

You have to enable the β€œallowJS” flag in your β€œtsconfig.json” file:

tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"allowJs": true
}
}

Alternatively, you can enable it through the TypeScript Compiler CLI:

1
tsc mycode.js --allowJs

TS7006

error TS7006: Parameter β€˜personβ€˜ implicitly has an β€˜anyβ€˜ type.

Broken Code ❌

main.ts
1
2
3
function greeter(person) {
return `Hello, ${person}`;
}
tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"noImplicitAny": true
}
}

Fixed Code βœ”οΈ

You have to define the type for the argument named person:

main.ts
1
2
3
function greeter(person: string) {
return `Hello, ${person}`;
}

Alternative, but not recommend:


TS7008

error TS7008: Member β€˜nameβ€˜ implicitly has an β€˜any’ type.

Broken Code ❌

1
2
3
abstract class Person {
accessor name;
}

Fixed Code βœ”οΈ

To fix the problem, you can initialize the class member so that TypeScript can infer the type:

1
2
3
abstract class Person {
accessor name = 'unknown';
}

Alternatively, you can annotate the type:

1
2
3
abstract class Person {
accessor name: string;
}

TS7009

error TS7009: β€˜new’ expression, whose target lacks a construct signature, implicitly has an β€˜any’ type.

Broken Code ❌

1
2
3
export function getPromise(): Promise<void> {
return new Promise.resolve();
}

Fixed Code βœ”οΈ

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:

1
2
3
export function getPromise(): Promise<void> {
return Promise.resolve();
}

Alternatively, you can make use of the constructor:

1
2
3
4
5
export function getPromise(): Promise<void> {
return new Promise(resolve => {
resolve();
});
}

TS7010

error TS7010: β€˜sumβ€˜, which lacks return-type annotation, implicitly has an β€˜anyβ€˜ return type.

Broken Code ❌

1
2
3
namespace MyModule {
export function sum(a: number, b: number);
}

Fixed Code βœ”οΈ

You have to add a return-type annotation and preferably a function implementation:

1
2
3
4
5
namespace MyModule {
export function sum(a: number, b: number): number {
return a + b;
}
}

TS7016

error TS7016: Could not find a declaration file for module β€˜uuidjsβ€˜.

Broken Code ❌

1
import UUID = require('uuidjs');

Fixed Code βœ”οΈ

Solution 1

The problem shows that uuidjs is a plain JavaScript module and doesn’t ship with TypeScript declaration files (.d.ts). That’s why we have to use the CommonJS import syntax to import this module in a Node.js environment:

main.ts
1
const UUID = require('uuidjs');

Solution 2

A proper fix would be to have a uuidjs.d.ts as part of uuidjs: https://github.com/LiosK/UUID.js/issues/6

Example:

uuidjs.d.ts
1
2
3
declare class UUID {
static generate(): string;
}
main.ts
1
2
import UUID from 'uuidjs';
const id = UUID.generate();

Solution 3

If external typings are available in the DefinitelyTyped repository, then you can also install external declarations from there:

1
npm i --save-dev @types/uuidjs

Solution 4

If there are no declarations available and you want to use the module (in this case uuidjs) with standard import syntax (not CommonJS), then you can create a shorthand ambient module declaration by creating a β€œ*.d.ts” file and writing the following into it:

types.d.ts
1
declare module "uuidjs";

Video Tutorial


TS7017

error TS7017: Element implicitly has an β€˜anyβ€˜ type because type β€˜{}β€˜ has no index signature.

Broken Code ❌

1
const recipients = {};

Fixed Code βœ”οΈ

You have to define the type for indexing your object properties (object["index"]):

1
const recipients: {[index: string]: number} = {};

The name of the index can be freely chosen:

1
const recipients: {[myKey: string]: number} = {};

How to fix such errors in interfaces:

1
2
3
interface Recipients {
[index: string]: number;
}

Alternative, but not recommend:

error TS7017: Element implicitly has an β€˜anyβ€˜ type because type β€˜typeof globalThisβ€˜ has no index signature.

Broken Code ❌

1
global.client = new APIClient(APIClient.URL_DEMO, 'global-demo-api-key');

Fixed Code βœ”οΈ

1
2
3
4
5
declare global {
var client: APIClient;
}

global.client = new APIClient(APIClient.URL_DEMO, 'global-demo-api-key');

Reference:

Video Tutorial


TS7022

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.

Broken Code ❌

1
var window = window || null;
tsconfig.json
1
2
3
4
{
"compilerOptions": {
"lib": ["es2017"]
}

Fixed Code βœ”οΈ

The above error can occur when TypeScript doesn’t know about the window interface. Make sure to add β€œdom” to your list of known runtime libraries in your compiler options:

tsconfig.json
1
2
3
4
{
"compilerOptions": {
"lib": ["dom", "es2017"]
}

TS7023

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.

Broken Code ❌

1
2
3
function fibonacci(n) {
return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}

Fixed Code βœ”οΈ

To avoid the implicit typing of any for the return type, you have to add a return type annotation:

1
2
3
function fibonacci(n): number {
return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}

TS7026

error TS7026: JSX element implicitly has type β€˜any’ because no interface β€˜JSX.IntrinsicElements’ exists.

Broken Code ❌

1
2
3
4
5
function App() {
return <p>My App!</p>;
}

export default App;

Fixed Code βœ”οΈ

The global JSX namespace is declared in @types/react. You have to install the @types/react package to make use of it:

1
yarn add --dev @types/react

TS7027

error TS7027: Unreachable code detected.

Broken Code ❌

1
2
process.exit(0);
console.log('Hello, World!');

Fixed Code βœ”οΈ

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:

1
2
console.log('Hello, World!');
process.exit(0);

TS7030

error TS7030: Not all code paths return a value.

Broken Code ❌

1
2
3
4
5
function getFlightType(type: 1 | 2) {
if (type === 1) {
return 'Return trip';
}
}

Fixed Code βœ”οΈ

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.

Always return a value:

1
2
3
4
5
6
function getFlightType(type: 1 | 2) {
if (type === 1) {
return 'Return trip';
}
return 'One way';
}

Add general else:

1
2
3
4
5
6
7
function getFlightType(type: 1 | 2) {
if (type === 1) {
return 'Return trip';
} else {
return 'One way';
}
}

Handle all cases:

1
2
3
4
5
6
7
8
function getFlightType(type: 1 | 2) {
switch (type) {
case 1:
return 'Return trip';
case 2:
return 'One way';
}
}

Add default case:

1
2
3
4
5
6
7
8
function getFlightType(type: 1 | 2) {
switch (type) {
case 1:
return 'Return trip';
default:
return 'One way';
}
}

Define that the return type can be void:

1
2
3
4
5
function getFlightType(type: 1 | 2): string | void {
if (type === 1) {
return 'Return trip';
}
}

Video Tutorial


TS7031

error TS7031: Binding element β€˜age’ implicitly has an β€˜any’ type.

Broken Code ❌

1
2
3
export function printAge({age}): void {
console.log(age);
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
type Person = {
age: number;
name: string;
};

export function printAge({age}: Person): void {
console.log(age);
}

TS7034

error TS7034: Variable β€˜expectationsβ€˜ implicitly has type β€˜any[]β€˜ in some locations where its type cannot be determined.

Broken Code ❌

1
const expectations = [];

Fixed Code βœ”οΈ

An array can collect values of different types, so we have to tell TypeScript which types we want to collect:

1
const expectations: string[] = [];

If we want to specify multiple types, we have to define a union type:

1
2
3
const expectations: (string | number)[] = [];
expectations.push('1');
expectations.push(2);

Alternative #1:

Create a type alias and provide a type annotation for the expectations constant:

1
2
3
4
type ArrayInput = string | number;
const expectations: ArrayInput[] = [];
expectations.push('1');
expectations.push(2);

Alternative #2:

Use concrete values to initialize the expectations array, so TypeScript can infer the array type for you:

1
2
3
const expectations = [-1, '0'];
expectations.push('1');
expectations.push(2);

Unrecommended solution:


TS7041

error TS7041: The containing arrow function captures the global value of β€˜thisβ€˜.

Broken Code ❌

1
2
3
4
5
6
const myObject = {
name: 'Benny',
myMethod: () => {
return this.name;
},
};

Fixed Code βœ”οΈ

Using this is not allowed in arrow functions (source) because arrow functions aren’t made to work with call, apply and/or bind methods (source). We have to replace our arrow function with an anonymous function declaration to prevent that our this context gets captured:

1
2
3
4
5
6
const myObject = {
name: 'Benny',
myMethod: function () {
return this.name;
},
};

Since ECMAScript 2015 (ES6) this can be shortened (Object Literal Property Value Shorthand) to:

1
2
3
4
5
6
const myObject = {
name: 'Benny',
myMethod() {
return this.name;
},
};

TS7044

error TS7044: Parameter β€˜aβ€˜ implicitly has an β€˜anyβ€˜ type, but a better type may be inferred from usage.

Broken Code ❌

1
const multiply = (a, b) => a * b;

Fixed Code βœ”οΈ

From the body of the arrow function expression, TypeScript can see by the * that a and b may be of type number:

1
const multiply = (a: number, b: number) => a * b;

TS7053

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β€˜.

Broken Code ❌

1
2
3
4
5
6
7
interface Person {
name: string;
}

function getValue(person: Person, key: string): string {
return person[key];
}

Fixed Code βœ”οΈ

There are multiple ways to solve the error. You can define an index signature for the Person interface which will allow all strings:

1
2
3
4
5
6
7
8
interface Person {
[index: string]: string;
name: string;
}

function getValue(person: Person, key: string): string {
return person[key];
}

However, this is not recommend as it will allow you to access keys that are not defined (like age):

1
2
3
4
5
6
7
8
9
10
interface Person {
[index: string]: string;
name: string;
}

function getValue(person: Person, key: string): string {
return person[key];
}

console.log(getValue({name: 'Benny'}, 'age')); // returns `undefined`

The better solution is using the keyof type operator which creates a literal union of its keys:

1
2
3
4
5
6
7
interface Person {
name: string;
}

function getValue(person: Person, key: keyof Person): string {
return person[key];
}

TS8020

error TS8020: JSDoc types can only be used inside documentation comments.

Broken Code ❌

1
2
3
function add(a: number, b: number, c: number?): number {
return a + b;
}

Fixed Code βœ”οΈ

If you wanted to make c optional:

1
2
3
function add(a: number, b: number, c?: number): number {
return a + b;
}

If you wanted to document c with JSDoc:

1
2
3
4
5
6
7
8
/**
* @param a Initial quantity
* @param b Amount to add
* @param [c] Optional number to add
*/
function add(a: number, b: number, c: number): number {
return a + b;
}

TS17000

error TS17000: JSX attributes must only be assigned a non-empty β€˜expression’.

Broken Code ❌

1
<Typography variant={}>Title</Typography>

Fixed Code βœ”οΈ

You can’t use an empty expression ({}) in JSX attributes:

1
<Typography variant={'h2'}>Title</Typography>

TS17004

error TS17004: Cannot use JSX unless the β€˜β€“jsx’ flag is provided.

Broken Code ❌

1
2
3
4
5
function App() {
return <p>My App!</p>;
}

export default App;

Fixed Code βœ”οΈ

You have to add a configuration for β€œjsx” to your β€œtsconfig.json” file:

tsconfig.json
1
2
3
4
5
{
"compilerOptions": {
"jsx": "react"
}
}

TS17009

error TS17009: β€˜super’ must be called before accessing β€˜this’ in the constructor of a derived class.

Broken Code ❌

1
2
3
4
5
6
7
8
9
10
11
12
abstract class Animal {
abstract name: string;
}

class Dog extends Animal {
public name;

constructor(name: string) {
this.name = name;
super();
}
}

Fixed Code βœ”οΈ

1
2
3
4
5
6
7
8
9
10
11
12
abstract class Animal {
abstract name: string;
}

class Dog extends Animal {
public name;

constructor(name: string) {
super();
this.name = name;
}
}

TS18004

error TS18004: No value exists in scope for the shorthand property β€˜ageβ€˜. Either declare one or provide an initializer.

Broken Code ❌

1
2
3
4
5
6
7
export function getPerson() {
return {
age,
fistName: 'Benny',
lastName: 'Neugebauer',
};
}

Fixed Code βœ”οΈ

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:

1
2
3
4
5
6
7
8
export function getPerson() {
const age = 34;
return {
age,
fistName: 'Benny',
lastName: 'Neugebauer',
};
}

Alternatively, you can avoid using the shorthand property name syntax:

1
2
3
4
5
6
7
export function getPerson() {
return {
age: 34,
fistName: 'Benny',
lastName: 'Neugebauer',
};
}

TS18016

error TS18016: Private identifiers are not allowed outside class bodies.

Broken Code ❌

1
2
3
interface Person {
#age: number;
}

Fixed Code βœ”οΈ

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:

1
2
3
class Person {
#age: number;
}

TS18046

error TS18046: β€˜errorβ€˜ is of type β€˜unknownβ€˜.

Broken Code ❌

1
2
3
4
5
6
7
8
9
async function test() {
try {
await Promise.reject(new Error('This is a test'));
} catch (error: unknown) {
console.error(error.message);
}
}

test();

Fixed Code βœ”οΈ

If you set the useUnknownInCatchVariables option to true in your tsconfig.json file, you may encounter the TS18046 error.

Enabling the 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 or an assertion function to access properties on an object of type unknown:

1
2
3
4
5
6
7
8
9
10
11
async function test() {
try {
await Promise.reject(new Error('This is a test'));
} catch (error: unknown) {
if (error instanceof Error) {
console.error(error.message);
}
}
}

test();

TS18048

error TS18048: β€˜textβ€˜ is possibly β€˜undefinedβ€˜.

Broken Code ❌

1
2
3
function getShortenedText(text?: string): string {
return text.slice(0, 5);
}

Fixed Code βœ”οΈ

If the text parameter is optional, it can potentially be of type unknown. When the type is unknown, accessing methods like Array.slice is not possible.

To solve this error, we need to employ a type guard to ensure that text is of type string:

1
2
3
4
5
6
function getShortenedText(text?: string): string {
if (typeof text === 'string') {
return text.slice(0, 5);
}
return '';
}

Note: We also need to employ a default return value to maintain the function return type of string.


TS80005

error TS80005: β€˜require’ call may be converted to an import.

Broken Code ❌

1
const pkg = require('../package.json');

Fixed Code βœ”οΈ

1
import pkg from '../package.json';