2

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

0

2 Answers 2

1

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"
}
Sign up to request clarification or add additional context in comments.

4 Comments

Another issue! If T[K] is an array it cannot be assigned to "something", here is a playground
Honestly, I don't think this is a problem with the given solution, you actually changed the original problem. (without updating the question) As you know number is a primitive value, but number[] is an object. This completely changes the problem. Please create another question, and add the link here, and I'll gladly provide a new answer to your new problem.
You are right. Here is the new question!
Answered to the other question, please comment on my answer, if the new given solution does not solve your problem.
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.