Home > Blockchain >  Typescript conditional extends with nested object
Typescript conditional extends with nested object

Time:07-04

I am building a type that checks if a member of a class-type is an object and if so, a specific type must be assigned. I provide a more explanatory example below.

Here we have the class example we are going to use.

declare class myObject {
    name?: string
    id?: number
    parent?: {
        child: number
    }
}

Here we have the type i am trying to make

type myType<T> = {
    [K in keyof T]: T[K] extends {[k:string]:any} ? T[K] : "something"
}

It should check that parent member is in fact an object of that type and allow something like this

const example: myType<myObject> = {
    parent: {
        child: 0
    },
    name: "something"
    id: "something"

But it doesn't because parent? doesn't get checked successfully against {[k:string]:any}. This happens because parent? is an optional member. If i change parent? to parent it works as expected. To try and work around this I tried switching {[k:string]:any} with {[Z in keyof T[K]]?: T[K][Z]} but i observed the same exact behaviour.

A link to TS Playground

CodePudding user response:

You are right when you say this happens because parent? is an optional member.

But what does it mean to be an optional member?

In JS it means the property can either have a value or be undefined.

In TS, it means that the type of parent? is actually something like: {[k:string]: any} | undefined

The code below solves the error on the linked TS playground.

type myType<T> = {
    [K in keyof T]?: T[K] extends ({[k:string]: any} | undefined) ? T[K] : "something"
}

CodePudding user response:

If I understand your problem correctly, then you can do the following:

type MyType<T> = {
    [K in keyof T]: T[K] extends {[k:string]:any} | undefined ? T[K] : "something"
}

The ? gives the property the possibility to be undefined (optional), therefore you can replace {[k:string]:any} with [k:string]:any} | undefined.

  • Related