00059-hard-get-optional

Back

// your answers
type GetOptional<T> = {
  [key in keyof T as {} extends Pick<T,key> ? key:never]:T[key]
}

Solution by sciencefunq #32916

这个挑战逻辑一样

type GetOptional<T, M = Required<T>> = {
  [P in keyof (T | M) as Equal<T[P], M[P]> extends true ? never : P]: T[P];
};

Solution by Vampirelee #32603

type GetOptional<T> = {[P in keyof T as T[P] extends Required<T>[P] ? never: P]: T[P]}

// here Required<T>[P] ? never :P   remove the required key and pic optional one

Solution by wubrafiq807 #32561

// your answers
type GetOptional<T> = {
  [K in keyof T as T[K] extends Required<T>[K] ? never : K]: T[K]
}

Solution by laqudee #32361

type GetOptional = { [key in keyof T as (T[key] extends {[reqKey in keyof T]-?: T[reqKey]}[key] ? never : key)] : T[key] }

Solution by harshtalks #31670

type GetOptional<T> = {
  [P in keyof T as T[P] extends Required<T>[P] ? never : P]: T[P];
};

Solution by vipulpathak113 #31320

type GetOptional<T> = {
  [K in keyof T as Pick<T, K> extends Required<Pick<T, K>> ? never : K]: T[K]
}

Solution by dreamluo-plus #30719

type Exclude<A, B> = {
  [K in keyof A & keyof B]:
    A[K] extends B[K] ? never : K
};

type OptionalKeys<T> = Exclude<T, Required<T>>[keyof T];

type GetOptional<T> = {
  [K in OptionalKeys<T>]?: T[K]
};

Solution by denysoblohin-okta #30427

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

Solution by gyermakavets #28281

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

Solution by smileboyi #27332

// 你的答案
type GetOptional<T> = {
  [
    P in keyof T as
      T[P] extends Required<T>[P]
      ? never
      : P
  ]: T[P];
};

Solution by kiki-zjq #25984

// your answers
type GetOptional<T extends object> = {
  [K in keyof T as T[K] extends Required<T>[K] ? never : K]: T[K]
}

Solution by studymachiney #24956

type GetOptional<T> = { [P in keyof T as T[P] extends Required<T>[P] ? never : P]: T[P] };  //-?后类型仍相同则为必选字段

Solution by E-uler #24670

type GetOptional<T> = {
  [Key in keyof T as T[Key] extends Required<T>[Key] ? never : Key]: T[Key]
}

Solution by NeylonR #24415


type GetOptional<T extends Record<string, any>> = matchOptionalKey<T, GetKeys<T>>;

type GetKeys<T> = {
  [k in keyof T]: k;
};

type matchOptionalKey<T extends Record<string, any>, U extends Record<string, any>, k = keyof U> = k extends keyof U ? undefined extends U[k] ? {
  [m in k]?: m extends keyof T ? T[m] : never;
} : never : never;

Solution by yolilufei #24357

// 你的答案

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

Solution by walker-hzx #24297

type GetOptional<T> = {[Key in keyof T as  {} extends Pick<T, Key> ? Key: never]: T[Key]}

Solution by sabercc #23857

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

Solution by snakeUni #23410

// 你的答案
type GetOptional<T> = {
  [K in keyof T as ({} extends Pick<T, K> ? K : never)]: T[K]
}

Solution by jxhhdx #22818

type GetOptional<T> = {
  [Key in keyof T as T[Key] extends Required<T>[Key] ? never : Key]: T[Key]
}

Solution by drylint #22193

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

Solution by kfess #21918

type GetRequired<T> = {
  [key in keyof T as T[key] extends Required<T>[key] ? key : never] : T[key]
}

type GetOptional<T> = Omit<T, keyof GetRequired<T>>;

Solution by Karamuto #21883

// 你的答案
type GetOptional<T>
    = { [K in keyof T as T[K] extends { [K in keyof T]-?: T[K] }[K] ? never : K]: T[K] }

Solution by goddnsgit #21844

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

Solution by jgjgill #21822

type GetOptional<T> = {
  [key in keyof T as T extends { [maybeOptKey in key]-?: any } ? never : key]?: T[key]
}

Solution by Drincann #21197

type UnionToIntersection<U> = (
  U extends U ? (x: U) => unknown : never
) extends (x: infer R) => unknown
  ? R
  : never;

type GetOptional<T, S extends keyof T = keyof T> = Partial<
  UnionToIntersection<
    S extends S
      ? Equal<
          Pick<T, S>,
          Partial<{
            [P in S]: T[S];
          }>
        > extends true
        ? Pick<T, S>
        : never
      : never
  >
>;

Solution by so11y #21018

type Not<B extends boolean> = B extends true ? false : true;
type If<B extends boolean, TRet> = B extends true ? TRet : never;

type IsRequired<T, TKey extends keyof T> = Equal<Pick<T, TKey>, Required<Pick<T, TKey>>>;
type IsOptional<T, TKey extends keyof T> = Not<IsRequired<T, TKey>>;

type GetOptional<T> = {
  [TKey in keyof T as If<IsOptional<T, TKey>, TKey>] : T[TKey]
}

Solution by mdakram28 #20655

// your answers
type OptionalType<T,P extends keyof T> = {
  [K in keyof T ] : T[K]
}[P]
type notOptionalType<T,P extends keyof T> = {
  [K in keyof T ]-? : T[K]
}[P]
type GetOptional<T> = {
  [K in keyof T as OptionalType<T,K> extends notOptionalType<T,K> ? never : K] : T[K]
}

Solution by YqxLzx #20444

// your answers
type GetOptional<T> = {
  [Key in keyof T as Omit<T, Key> extends T ? Key : never]: T[Key];
};

Solution by fengjinlong #20166

type IsOptionalKey<T, K extends keyof T> =
  {[P in K]+?: T[P]} extends {[P in K]: T[P]}
    ? true
    : false 

type GetOptional<T> = {
  [P in keyof T as IsOptionalKey<T, P> extends true ? P : never]: T[P]
}

playground

In order to better explain the solution, I didn't reduce it to a minimum version.

The key point is:

Pick anyone you like, the 4 statements above is describing the same thing.

Now look at IsOptionalKey. On the left side of extends, we build an object with an optional field, much like {a?: 1}, and on the right side, it's an object with original field a, which is like {a?: 1} or {a: 1}. If the field is optional, so the expression is {a?: 1} extends {a?: 1} which resolves to true, but if the field is required, the expression would be {a?: 1} extends {a: 1}, as we stated before, which resolves to false. That's all about how IsOptionalKey works.

With the util IsOptionalKey, the remainling is straghtforward and doesn't need more words to explain.

Related:

Solution by zhaoyao91 #20149