Skip to content

Instantly share code, notes, and snippets.

@Jack-Works

Jack-Works/explain.md

Last active Nov 12, 2020
Embed
What would you like to do?
FAQ: Why TypeScript is correct? / Why TypeScript cannot express this?

Frequently asked TypeScript question

I think my code is correct! Why it is complaining type error to me?

How can I do something in TypeScript?

Case 1: Add function

function add<T extends number | bigint>(left: T, right: T): T {
    return left + right
}

TS2365: Operator '+' cannot be applied to types 'T' and 'T'.

Explain: Consider this code:

add<number | bigint>(1, 2n)

This call is valid but it will cause a runtime error therefore TypeScript is correct to give the error in the implementation of add.

Because in TypeScript you cannot require the generics T is a "concrete" type that only can be "number" or "bigint" but not "number | bigint", therefore this error is not a false-positive.

One of the correct way to implement an add function is:

const add: {
  (x: number, y: number): number
  (x: bigint, y: bigint): bigint
} = ((a: any, b: any) => a + b) as any

add(1, 2) // ok
add(1n, 2n) // ok
add(1, 2n) // error

Case 2: Incompatible index signatures

How to write a type that have index signatures with incompatible named properties?

interface T {
    // @ts-ignore
    name: string
    [index: string]: number
}

Explain:

When looking up properties on a type, TypeScript first find if there is matching named properties, in this case, name. If there is not, the compiler will try to lookup if there is index signature.

Without @ts-ignore the compiler will report "string" is not assignable to "number" but that error doesn't make type T becomes any. By ignoring the error, we create a type that have incompatible signatures.

To create an instance of this type, you will need to use as any because when assigning, the compiler first check if name is matching string (the named signature), then also check if it is matching the index signature (number in the case) which is not possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment