TypeScript如何定义禁止包含SecretString类型值的任意对象类型
解决方案
可以实现,以下是支持嵌套检查(覆盖对象、数组场景)的完整方案:
首先定义递归检查类型,只要类型中存在SecretString就返回never触发类型不兼容:
// 递归检查所有属性/元素,只要存在 SecretString 就返回 never type NoSecrets<T> = T extends SecretString ? never : T extends object ? { [K in keyof T]: NoSecrets<T[K]> } : T;
修改日志函数的类型签名,要求传入的上下文参数必须符合无SecretString的规则:
type Logger = { info: <T extends object>( message: string, // 传入的context不符合无Secret规则时,类型不兼容触发编译报错 context: T extends NoSecrets<T> ? T : never ) => void; // error、warn等其他日志方法同理修改签名即可 } declare const logger: Logger;
效果验证
你给出的风险场景会直接触发编译错误:
const keys = decryptString(encryptedKeys); // 编译报错:存在SecretString类型属性 logger.info('This should not compile!', { valueThatIsOk: 'this is ok', valueThatShouldFail: keys }); // 正常编译:无SecretString类型值 logger.info('Normal log', { publicStr: '公开内容', count: 123, nested: { foo: 'bar' } }); // 嵌套场景也会触发报错 logger.info('Nested secret', { user: { password: keys // 此处有SecretString,触发报错 } }); // 数组包含SecretString也会触发报错 logger.info('Array secret', { secrets: [keys, '普通字符串'] // 此处有SecretString,触发报错 });
如果仅需要一级属性检查(不检查嵌套对象),可以用简化版本:
// 仅检查一级属性,不递归检查嵌套内容 type NoSecretsOneLevel<T extends object> = { [K in keyof T]: T[K] extends SecretString ? never : T[K] } // 对应修改日志函数签名即可 type Logger = { info: <T extends object>( message: string, context: T extends NoSecretsOneLevel<T> ? T : never ) => void; }
内容的提问来源于stack exchange,提问作者Kristian Dupont
相关产品推荐
相关产品推荐

