0

我整理了一个简单的 Store 实现,它将一个不可变的 javascript 'root' 项包装为状态。

操作允许使用partition键从父存储中派生子存储。新 Store 的根状态是在该键处找到的原始根状态的子状态。子存储在其他方面的功能与根存储相同。

该实现似乎工作正常,但不幸的是,当(出于其他原因)我需要将可能的根项目限制为extends object. 当然只有一些子项会满足这个约束,这意味着打字稿会发现递归分区可能出现的错误。

我认为我需要将分区键参数限制为解析为extends object. 我不确定该怎么做。

在这次干预之前,一切在实施和打字方面都运行良好。

一个看起来积极和编译的定义(在添加对象约束之前)是这个......

type Partitioner<State> = <Key extends keyof State>(key:Key) => Store<State[Key]>;

interface Store<State> {
    read():State
    write(state:State):void;
    partition: Partitioner<State>
}

class BasicStore<State> implements Store<State> {
    state:State;
    constructor(state:State){
        this.state = state;
    }
    read = () => this.state;
    write = (state:State) => this.state = state;
    partition:Partitioner<State> = <Key extends keyof State>(key:Key) => new BasicPartition(this, key);
}

export class BasicPartition<State, Key extends keyof State>
  implements Store<State[Key]> {
  constructor(readonly store: Store<State>, readonly key: Key) {}
  read = () => this.store.read()[this.key];
  write = (state:State[Key]) => this.store.write({
      ...this.store.read(),
      [this.key]:state
  })
  partition:Partitioner<State[Key]> = <SubKey extends keyof State[Key]>(subKey:SubKey) => new BasicPartition(this, subKey);
}

打字稿游乐场

编译错误可以在相同代码的以下版本中看到,其中 BasicStore 和 BasicPartition 将它们的状态限制为extends object...

type Partitioner<State> = <Key extends keyof State>(key:Key) => Store<State[Key]>;

interface Store<State> {
    read():State
    write(state:State):void;
    partition: Partitioner<State>
}

class BasicStore<State extends object> implements Store<State> {
    state:State;
    constructor(state:State){
        this.state = state;
    }
    read = () => this.state;
    write = (state:State) => this.state = state;
    partition:Partitioner<State> = <Key extends keyof State>(key:Key) => new BasicPartition(this, key);
}

export class BasicPartition<State extends object, Key extends keyof State>
  implements Store<State[Key]> {
  constructor(readonly store: Store<State>, readonly key: Key) {}
  read = () => this.store.read()[this.key];
  write = (state:State[Key]) => this.store.write({
      ...this.store.read(),
      [this.key]:state
  })
  partition:Partitioner<State[Key]> = <SubKey extends keyof State[Key]>(subKey:SubKey) => new BasicPartition(this, subKey);
}

最后一行报错Argument of type 'this' is not assignable to parameter of type 'Store<object>'typescript playground

如何将有效的 Key 参数限制为分区函数,以便 State[Key] 始终是一个对象,从而消除无效的代码路径。在伪代码中,我认为 Partitioner 通用参数可能类似于Key extends keyof State where State[Key] extends object. 在这个联合解决的never地方,根本没有有效的论据可供调用partition

4

0 回答 0