1

I am trying to type a function addId that inputs an object and returns the same object but adds a property _id: string to every sub-object.

Say for example that the input is an object constructed from the following class.

class A {
  a: number
  b: { bb: number }
  c: number[]

  constructor() {
    this.a = 1
    this.b = { bb: 2 }
    this.c = [1,2,3]
  }
}
const a = new A()

In this case addId(a) would return

A {
  _id: 'id1'
  a: 1
  b: { bb: 2, _id: 'id2' }
  c: [1,2,3]
}

The parameter to addId can be an object of any class, not specifically the class A. The parameter can be built up recursively from json, objects, and arrays and can have an arbitrary nesting depth.

I am not looking for an implementation of addId, just the return type. I think the solutions would use similar techniques to the ones used for the type for DeepReadonly<T> defined here: https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts

1 Answer 1

4

How about:

type Smart<T> =
  T extends Function ? T :
  T extends object ? (
    { [K in keyof T]: Smart<T[K]> } &
    (T extends readonly any[] ? unknown : { _id: string })
  ) : T

If T is a non-function object, then you definitely want to recurse down into it and do Smart<T> for each property. This will work for both arrays and regular objects. But you only want to add the _id property to non-array objects, which is why I do that T extends readonly any[] check. You can confirm that it gives the output you expect:

declare class A {
  a: number
  b: { bb: number }
  c: number[]
}
type SmartA = Smart<A>;
/*
type SmartA = {
    a: number;
    b: {
        bb: number;
    } & {
        _id: string;
    };
    c: number[];
} & {
    _id: string;
}
*/

Playground link to code

Sign up to request clarification or add additional context in comments.

4 Comments

Hi jcalz. Perhaps I can explain my edit. The general editing ethic here is rather like Wikipedia - contributors are encouraged to write in a technical fashion, and with succinctness. Editors take the same approach - material is edited to improve spelling, grammar, brevity, and so forth.
Editors see "hope that helps" and "good luck" and signatures and other sign-offs often, and they are generally removed on sight. It's not personal - we don't remove them from one person and not another.
I have restored this edit but I will be unhappy if I get alerted to a string of these in the near future. If you must make minor edits to my answers, please pace yourself (I've had some unpleasant experiences in the past with serial editors).
Thanks for the restore, appreciated. I sympathise with the issue of serial editing in general - my understanding is that it is somewhat moderator-approved, but with caveats (particularly around edit rate, as you say). I shall try to go easy!

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.