Typescript 将函数参数约束为“永不”,以消除映射类型不存在的无效代码路径';不满足约束条件

Typescript 将函数参数约束为“永不”,以消除映射类型不存在的无效代码路径';不满足约束条件,typescript,recursion,store,mapped-types,keyof,Typescript,Recursion,Store,Mapped Types,Keyof,我编写了一个简单的存储实现,它将不可变的javascript“根”项包装为状态 分区操作允许使用密钥从父存储派生子存储。新存储的根状态是在该键处找到的原始根状态的子级。否则,子存储的功能与根存储相同 该实现似乎工作正常,但不幸的是,当(出于其他原因)需要我将可能的根项限制为extends object时,分区操作出现编译错误。当然,只有一些子项会满足此约束,这意味着typescript会发现递归分区中可能存在的错误 我认为我需要将分区键参数限制为解析为扩展对象的子对象的键。我不知道怎么做 在这次

我编写了一个简单的存储实现,它将不可变的javascript“根”项包装为状态

分区
操作允许使用密钥从父存储派生子存储。新存储的根状态是在该键处找到的原始根状态的子级。否则,子存储的功能与根存储相同

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

我认为我需要将分区键参数限制为解析为扩展对象的子对象的键。我不知道怎么做

在这次干预之前,在执行和打字方面,一切都进展顺利

在添加对象约束之前,一个看起来积极且经过编译的定义是

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);
}
“this”类型的最后一行
参数报告了一个错误,该参数不可分配给“Store”类型的参数。
请参阅


如何将有效的键参数限制在分区函数中,使State[Key]始终是一个对象,从而消除无效的代码路径。在伪代码中,我认为Partitioner泛型参数可能类似于
Key extends-keyof-State,其中State[Key]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);
}