有条件申请?每个属性的映射类型中的修饰符

问题描述

来自 TypeScript 文档:

// Removes 'optional' attributes from a type's properties
type Concrete<Type> = {
  [Property in keyof Type]-?: Type[Property];
};

type MaybeUser = {
  id: string;
  name?: string;
  age?: number;
};

我知道我可以将 ? 修饰符添加所有属性,如果我想根据 extends 表达式逐个属性添加它怎么办?

行为如下:

// Not valid TypeScript
type Optionalize<T> = {
   [P in keyof T](?: T[P] extends SomeInterface): T[P];
}   

解决方法

相关 GitHub 问题:https://github.com/microsoft/TypeScript/issues/32562

  1. 提取类型中不匹配的 props,我们称之为 NonMatching
  2. 在第二种类型中提取匹配的 prop,比如 Matching
  3. 使用 extends infer 技术将两种类型相交
type TestType = {
  a: SomeInterface;
  b: string;
};

type Intersection<A,B> = A & B extends infer U
  ? { [P in keyof U]: U[P] }
  : never;

type Matching<T,SomeInterface> = {
  [K in keyof T]: T[K] extends SomeInterface ? K : never;
}[keyof T];

type NonMatching<T,SomeInterface> = {
  [K in keyof T]: T[K] extends SomeInterface ? never : K;
}[keyof T];

type DesiredOutcome = Intersection<
  Partial<Pick<TestType,Matching<TestType,SomeInterface>>>,Required<Pick<TestType,NonMatching<TestType,SomeInterface>>
>

{[K in keyof T]: T[K] extends SomeInterface ? K : never } 将每个匹配的键映射到它自己的字符串文字类型表示是一种解决方法,即给定 { a: never,b: SomeInterface } 你得到 { b: 'b' },然后使用indexed access types 你以字符串文字类型联合的形式获得匹配的属性