Simon Hessner
Simon Hessner

Reputation: 1837

TypesScript: Why does keyof {} have the type never?

I am confused by the keyof operator when applied to an empty object. Example code:

const o = {};
const k : Array<keyof typeof o> = [];
// k has type never[]

Why is the type never? I thought never is the return type of functions that never return. Should the type not be any[] instead?

When changing the object like this, the type makes sense:

const o = {a: 1, b: 2};
const k : Array<keyof typeof o> = []; 
// k has the type ("a" | "b")[]

I found this behaviour when implementing a function that returns the typed keys of an object:

function getKeys(o: object) {
    return Object.keys(o) as Array<keyof typeof o>;
}

The function has the return type never[] but should actually have (keyof typeof o)[] if I am correct

Upvotes: 6

Views: 6504

Answers (1)

leonardfactory
leonardfactory

Reputation: 3501

EDIT: Ok, so, after the update the questions is clearer to me. The problem here is that you are not using generics, so you are literally asking TS for the keys of object, not of SOME object.

You can re-arrange the function in this way:

function getKeys<O extends {}>(o: O) {
    return Object.keys(o) as Array<keyof O>;
}

So that it will accept a generic object of type O, and in this case keyof O will be typed exactly Array<keyof O>. For example:

const keys = getKeys({ a: 1, b: 2 });
// Now keys has type ("a" | "b")[]

Old answer before post edit:

never represents a value that can never occur, like explained in the TS Doc. This is the case, since there are no keys in the object. To understand it better, this statement from TS Doc may be helpful:

The never type is a subtype of, and assignable to, every type;

This means that, in this case, never is correctly a subtype of string, especially meaning "no string" and so "no key".

Upvotes: 5

Related Questions