如何为支持数组解构的AsyncStore定义正确TypeScript类型?
TypeScript类型定义:修复异步存储的解构类型问题
问题背景
需要为以下简化的JS函数定义TypeScript类型:
function asyncStore(initialValue) { return { ...createStore(initialValue), get 0() { return this }, 1: createStore('pending'), [Symbol.iterator]: function *() { yield this[0] yield this[1] } } } function createSomeEnhancedStore(sourceStore) { return { ...sourceStore, someEnhanceMethod() { /* ... */ } } } const [value, status] = createSomeEnhancedStore(asyncStore(0))
现有类型草稿如下:
/* Some deps */ interface Store<T> { value: T } type AnyStore = Store<any> function createStore<T>(initialValue: T): Store<T> { return { value: initialValue } } /* Types for function */ interface AsyncStore<T> extends Store<T> { 0: this, 1: Store<'pending' | 'fulfilled' | 'rejected'> } function asyncStore<T>(initialValue: T): AsyncStore<T> { return { ...createStore(initialValue), get 0() { return this }, 1: createStore('pending'), [Symbol.iterator]: function *() { yield this[0] yield this[1] } } } function createSomeEnhancedStore<T extends AnyStore>(sourceStore: T): T & { someEnhanceMethod(): void } { return { ...sourceStore, someEnhanceMethod() { /* ... */ } } } const [value, status] = createSomeEnhancedStore(asyncStore(0))
当前遇到的问题:
- 调用增强方法时类型校验正常:
const enhancedStore = createSomeEnhancedStore(asyncStore(0)) enhancedStore.someEnhanceMethod() // types ok enhancedStore[0].someEnhanceMethod() // types ok - 但数组解构时出现类型错误,尝试给
AsyncStore添加迭代器类型后,解构得到的value和status类型变成了联合类型this | Store<'pending' | 'fulfilled' | 'rejected'>,不符合预期(预期value为this类型,status为Store<'pending' | 'fulfilled' | 'rejected'>类型)。
问题分析
原来的迭代器类型Iterator<this | Store<...>>会让TS认为每次yield的值是联合类型,无法区分顺序。要让解构时能推断出固定顺序的具体类型,需要让迭代器返回固定长度的元组类型,明确第一个值是this,第二个是状态存储类型。
解决方案
修改AsyncStore接口的Symbol.iterator定义,指定其返回的迭代器会产出一个包含两个元素的元组,这样TS就能准确推断解构后每个变量的类型:
interface AsyncStore<T> extends Store<T> { 0: this; 1: Store<'pending' | 'fulfilled' | 'rejected'>; [Symbol.iterator]: () => IterableIterator<[this, Store<'pending' | 'fulfilled' | 'rejected'>]>; }
完整修正代码
/* Some deps */ interface Store<T> { value: T; } type AnyStore = Store<any>; function createStore<T>(initialValue: T): Store<T> { return { value: initialValue }; } /* Types for function */ interface AsyncStore<T> extends Store<T> { 0: this; 1: Store<'pending' | 'fulfilled' | 'rejected'>; [Symbol.iterator]: () => IterableIterator<[this, Store<'pending' | 'fulfilled' | 'rejected'>]>; } function asyncStore<T>(initialValue: T): AsyncStore<T> { return { ...createStore(initialValue), get 0() { return this; }, 1: createStore('pending'), [Symbol.iterator]: function* () { yield this[0]; yield this[1]; }, }; } function createSomeEnhancedStore<T extends AnyStore>(sourceStore: T): T & { someEnhanceMethod(): void } { return { ...sourceStore, someEnhanceMethod() { /* ... */ }, }; } // 现在解构类型正确:value为AsyncStore<number>,status为Store<'pending' | 'fulfilled' | 'rejected'> const [value, status] = createSomeEnhancedStore(asyncStore(0));
验证效果
- 解构后
value的类型为AsyncStore<number> & { someEnhanceMethod(): void },可以正常调用someEnhanceMethod(); status的类型为Store<'pending' | 'fulfilled' | 'rejected'>,符合预期;- 原有的增强方法调用仍然保持类型正确。
内容的提问来源于stack exchange,提问作者dangreen
相关产品推荐
相关产品推荐

