如何基于接口与对象,用泛型生成指定可选键转必填的新类型?
解决方法
要实现“将接口中存在于具体对象的可选键转为必填,其余键保持原有状态”的需求,核心是让TypeScript捕获对象实际存在的键,而非仅依赖接口的类型定义。
问题根源
你当前代码里,const person: personInterface = { ... } 强制把对象类型约束为personInterface,导致typeof person返回的是接口的完整类型,而非对象字面量的实际键集合。因此keyof typeof person会包含接口所有键(id/name/title),最终把所有属性都设为必填,不符合预期。
正确实现步骤
1. 改进工具类型
编写泛型类型,接受接口T和对象的实际类型U(需满足U extends T),提取U中的键并将其在T中转为必填:
type MakeRequiredFromObj<T, U extends T> = Omit<T, keyof U> & { [P in keyof U]-?: T[P]; };
2. 保留对象的实际类型
使用satisfies关键字(TypeScript 4.9+)确保对象符合接口约束的同时,保留其字面量的具体类型:
interface personInterface { id?: number; name?: string; title?: string; } // 用satisfies确保对象符合接口,但保留实际键的类型 const person = { id: 2, name: "John", } satisfies personInterface;
若你的TypeScript版本低于4.9,可通过交叉类型手动约束:
const person: personInterface & { id: number; name: string } = { id: 2, name: "John", };
3. 生成目标类型
现在可以生成符合需求的新类型:
type OptionalToRequiredData = MakeRequiredFromObj<personInterface, typeof person>; // 验证:id和name为必填,title仍为可选 const resultPerson: OptionalToRequiredData = { id: 2, name: 'John', // title可省略,或按需赋值 };
额外:工具函数简化推导
如果不想手动传递泛型参数,可写一个工具函数自动推导类型:
function createRequiredType<T>() { return function <U extends T>(obj: U): MakeRequiredFromObj<T, U> { return obj as MakeRequiredFromObj<T, U>; }; } // 使用方式 const resultPerson = createRequiredType<personInterface>()(person);
内容的提问来源于stack exchange,提问作者Николай Шляпников
相关产品推荐
相关产品推荐

