ts实现获取interface中可选字段生成新类型

interface ComplexObject {
  mandatory: string;
  title1?: string;
  title2?: string;
}
type GetOptional<T> = {};
type Option = GetOptional<ComplexObject>;
function createApp(option: Option) {
  // {title1?: string; title2?: string;}
}

上述的代码我们期望通过GetOptional处理后的Option属性为`{title1?: string; title2?: string;}``

提出接口的所有字段

interface ComplexObject {
  mandatory: string;
  title1?: string;
  title2?: string;
}
type GetOptional<T> = {
  [P in keyof T]: T[P];
};
type Option = GetOptional<ComplexObject>;
function createApp(option: Option) {}

在这里插入图片描述

上述代码就提出了ComplexObject的所有字段,如果我们想给字段重命名,那么下面代码可以帮我们实现

interface ComplexObject {
  mandatory: string;
  title1?: string;
  title2?: string;
}
type GetOptional<T> = {
  // Capitalize将属性名的第一个首字母大写
  [P in keyof T as `get${Capitalize<P & string>}`]: T[P];
};
type Option = GetOptional<ComplexObject>;
function createApp(option: Option) {}

在这里插入图片描述

仅保留可选属性

interface ComplexObject {
  mandatory: string;
  a: number;
  title1?: string;
  title2?: number;
}

type OptionalKeys<T> = {
  [K in keyof T]-?: T extends Record<K, T[K]> ? never : K;
}[keyof T];

type GetOptional<T> = Pick<T, OptionalKeys<T>>;

type Option = GetOptional<ComplexObject>;

function createApp(option: Option) {}

在这里插入图片描述

  • OptionalKeys<T>通过将每个可能的键K映射到它们自己或never上来计算类型T中的所有可选键。映射键的条件检查是建立在是否每个属性KT中是可选的(即不包含在T extends Record<K, T[K]>的属性K)
  • GetOptional<T> 用于生成一个新的类型,包含所有指定的属性,关于Pick使用请查看
    在 TypeScript 的高级类型操作中,[K in keyof T]-?表示一个映射类型 (Mapped Type),用于遍历类型T的所有键K。这里的目的是产生一个新类型,其中T的所有属性都是必需的,即没有可选属性,具体来说
  • K in keyof T:对于类型T中的每个键K
  • -?:这是一个修饰符,用于从属性前移除可选性。这意味着如果T中的属性K被标记为可选(属性名称后跟一个问号 ?,比如 title1?),-?会将其转换为必需属性

将保留的可选属性改为必填属性

只需要加上Required即可实现,关于Required用法请查看

interface ComplexObject {
  mandatory: string;
  a: number;
  title1?: string;
  title2?: number;
}

type OptionalKeys<T> = {
  [K in keyof T]-?: T extends Record<K, T[K]> ? never : K;
}[keyof T];

type GetOptional<T> = Pick<T, OptionalKeys<T>>;

type Option = Required<GetOptional<ComplexObject>>;

function createApp(option: Option) {}

在这里插入图片描述