Андрей
Андрей

Reputation: 55

How to select common parameters from two interfaces in Typescript?

Select must be not only by key name but by types of these params

For example:

    interface human {
      name: string,
      height: number,
      weight:number
    }

    interface robot {
      name: number,
      height: number,
      weight:number
    }

Result must be:

    interface commonHumanRobot{
      height: number,
      weight: number
    }

There is a solution based on the answer of @Acid Coder

type selectCommon<T extends object, B extends object> = {
  [key in keyof T as T[key] extends B[key&keyof B]? B[key&keyof B] extends T[key]? key:never:never]:T[key]
}

Upvotes: 0

Views: 362

Answers (2)

Acid Coder
Acid Coder

Reputation: 2746

interface human {
    name: string,
    height: number,
    weight: number
}

interface robot {
    name: number,
    height: number,
    weight: number
}

type SelectCommon<T, V> =
    { [K in keyof T]: T[K] extends V[K & keyof V] ? V[K & keyof V] extends T[K] ? T[K] : never : never }

type RemoveNeverType<T> = { [K in keyof T as T[K] extends never ? never : K]: T[K] }

type A = RemoveNeverType<SelectCommon<human, robot>>
//   ^?

enter image description here

playground

update: shorter using intersection &

interface human {
    name: string,
    height: number,
    weight: number,
    a: 1
}

interface robot {
    name: number,
    height: number,
    weight: number
}

type SelectCommon<T, V> =
    { [K in keyof T & keyof V as (T & V)[K] extends never ? never : K]: (T & V)[K] }

type A = SelectCommon<human, robot>
//   ^?

enter image description here playground

however this come with less safe type eg 1 & number is 1, in my longer example, this will result in never which I think is safer but I guess 1 & number is 1 does not have any risk, so it makes sense too

Upvotes: 1

Ali Ataf
Ali Ataf

Reputation: 689

type NonNeverKeys<Type1, Type2, Inter = Type1 & Type2> = {
    [Key in keyof Inter]: Inter[Key] extends never ? never : Key
}[keyof Inter];
type NonNeverIntersect<Type1, Type2> = Pick<Type1 & Type2, NonNeverKeys<Type1, Type2>>;

interface human {
  name: string,
  height: number,
  weight: number
}

interface robot {
  name: number,
  height: number,
  weight: number
}

const inter: NonNeverIntersect<human, robot>;

Upvotes: 1

Related Questions