简体   繁体   中英

I want to infer the number of keys of an object

I want to infer the number of keys of an object.

For an array, this works:

type LengthArray<T extends readonly any[]> = T["length"];
type Length = LengthArray<["ryan", 1, true, 90]>;
// Length is 4 :)

I'm trying to do this from an object:

type LengthObject<T> = Array<keyof T>["length"];
type Length = LengthObject<{ name: string; age: number }>;
// Length is number :(

I would need to know that in the above interface, the number of properties would be exactly 2, not "number".

At the end of the day, what I would most like to know is whether the object has no properties:

type LengthObject<T> = <?>

function infer<T>(o: T): LengthObject<T> extends 0 ? number : string {
    // ...
}
const r1 = infer({}); // r1 is number;
const r2 = infer({ name: "ryan" }); // r2 is string;

Detecting if an object type T has no keys can be trivially done by checking if keyof T is never .

function infer<T>(o: T): keyof T extends never ? number : string {
    return null!
}
const r1 = infer({}); // r1 is number;
const r2 = infer({ name: "ryan" }); // r2 is string;

A general purpose solution to get the number of properties of an object type is a bit trickier. We can distribute over the keys of T and build a tuple which has an element for each property in T . The number of properties is now the length of the tuple.

type LengthObject<T, K extends keyof T= keyof T> = [K] extends [never]
  ? []
  : K extends K ? [0, ...LengthObject<Omit<T, K>>] : never

type Length = LengthObject<{ name: string; age: number }>["length"]
//   ^? type Length = 2

Note that both of these solutions might or might not behave unexpectedly when index signatures are involved.


Playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM