移除TypeScript代码中any类型,实现泛型与Partial约束的类型安全
解决TypeScript泛型联合类型的类型安全问题
你的问题核心是TypeScript无法通过type字段的判断自动缩小泛型T的范围,导致Partial<T>无法直接匹配Partial<SportJournal>或Partial<ArtJournal>。下面提供两种类型安全的解决方案,完全移除any类型:
方案一:使用类型谓词(Type Predicates)收窄泛型类型
定义专门的类型判断函数,明确告诉TypeScript当前JournalState的具体类型,从而让编译器正确推断Partial<T>的类型:
type SportJournal = { type: 'S', sport: boolean, id: string} type ArtJournal = { type: 'A', art: boolean, id: string} type Journal = SportJournal | ArtJournal; type JournalState<T extends Journal> = {state: string, journal: T} const updateSportJournal = (journal: Partial<SportJournal>) => { console.log(journal)} const updateArtJournal = (journal: Partial<ArtJournal>) => { console.log(journal)} // 定义类型谓词函数,明确判断JournalState的具体类型 function isSportJournalState<T extends Journal>(state: JournalState<T>): state is JournalState<SportJournal> { return state.journal.type === 'S'; } function isArtJournalState<T extends Journal>(state: JournalState<T>): state is JournalState<ArtJournal> { return state.journal.type === 'A'; } const updateJournalState = <T extends Journal>(journalState: JournalState<T>, journal: Partial<T>) => { if (isSportJournalState(journalState)) { updateSportJournal(journal); // 无需any,类型自动匹配 } else if (isArtJournalState(journalState)) { updateArtJournal(journal); } }
方案二:使用联合类型参数确保类型匹配
直接将函数参数定义为联合类型,强制journalState和journal的类型一一对应,从根源避免类型不匹配的问题:
type SportJournal = { type: 'S', sport: boolean, id: string} type ArtJournal = { type: 'A', art: boolean, id: string} type Journal = SportJournal | ArtJournal; type JournalState<T extends Journal> = {state: string, journal: T} const updateSportJournal = (journal: Partial<SportJournal>) => { console.log(journal)} const updateArtJournal = (journal: Partial<ArtJournal>) => { console.log(journal)} // 定义联合类型的参数,确保journalState和journal类型匹配 type JournalUpdateParams = | { journalState: JournalState<SportJournal>, journal: Partial<SportJournal> } | { journalState: JournalState<ArtJournal>, journal: Partial<ArtJournal> }; const updateJournalState = ({ journalState, journal }: JournalUpdateParams) => { if (journalState.journal.type === 'S') { updateSportJournal(journal); } else { updateArtJournal(journal); } }
验证调用
两种方案都支持类型安全的调用,编译器会自动检查参数类型是否匹配:
// 正确调用:运动日志 const sportState: JournalState<SportJournal> = { state: 'active', journal: { type: 'S', sport: true, id: '1' } }; updateJournalState(sportState, { sport: false }); // 正确调用:艺术日志 const artState: JournalState<ArtJournal> = { state: 'draft', journal: { type: 'A', art: true, id: '2' } }; updateJournalState(artState, { art: false });
内容的提问来源于stack exchange,提问作者sandrozbinden
相关产品推荐
相关产品推荐

