我可以在不通过断言强制类型的情况下修复此打字稿编译器错误吗?
Can I fix this typescript compiler error without forcing the type by assertion?
在此typescript playground我写了一个最小的不可变(递归只读)类型和一个存储不可变的存储接口。
目前我的分区存储 class 的 read() 和 write() 函数存在编译错误,我想通过正确注释类型而不是进行类型断言来解决这个错误。这是顶级定义。
interface Store<State>{
read:() => Immutable<State>
write:(state:Immutable<State>) => Immutable<State>
}
export type ImmutableObject<T> =
{
readonly [K in keyof T]: Immutable<T[K]>;
}
;
export type Immutable<T> = T extends object
? ImmutableObject<T>
: T extends string | number | boolean | null
? Readonly<T>
: never;
当我从商店派生分区子商店时,我的问题就出现了。这意味着只需使用其声明的键之一选择状态的一个子部分,然后从中创建一个商店。
这是我的草稿实现,它需要注释断言来抑制编译错误...
class BasicStorePartition<SuperState, Key extends keyof SuperState>
implements Store<SuperState[Key]>{
constructor(
readonly store: Store<SuperState>,
readonly key: Key,
) {}
//this line requires the commented type assertion in order to compile
read = () => this.store.read()[this.key] // as unknown as Immutable<SuperState[Key]>
write = (state:Immutable<SuperState[Key]>) => {
this.store.write({
...this.store.read(),
[this.key]:state
});
return this.read()
}
}
编译报错如下。我希望这些解析为相同的类型并且不知道 string
作为键来自哪里,因为在源代码中没有以这种方式注释键...
Type 'ImmutableObject<SuperState[string]>' is not assignable to type 'Immutable<SuperState[Key]>'
Type 'Immutable<SuperState>[Key]' is not assignable to type 'Immutable<SuperState[Key]>'
可以通过简单地声明类型信息来修复编译,例如...
as unknown as Immutable<SuperState[Key]>
我想解决此编译错误,以便类型解析并与预期的只读类型对齐,而无需绕过编译器。任何人都可以找到这样做的方法吗?
欢迎提出有关改进该方法的任何其他意见。
恐怕编译器无法毫无疑问地知道您希望它推断的类型是正确的,即使在实践中它们可能是正确的(在打字稿)。
以下是我对您的问题的观察:
object
类型已弃用,请参阅 this question。显然人们对它的使用有疑问。
在我看来,如果您 99% 确定它是正确的,那么在您的 实现 中使用类型断言是可以的。编译器并不完美,而且永远不会。但永远不要从你的 public 接口 返回错误的类型,或者强迫你的函数的用户做断言。我遇到了很多 public 类型信息不佳或错误的库,这真的很令人沮丧。
我正在创作 Rimbu immutable collections library,其中我已尽最大努力使类型信息尽可能正确和精确。但是,如果您看起来 'under the hood' 可以这么说,代码中充满了类型断言,因为编译器,尤其是在更高级的情况下,只需要帮助。这在任何类型化语言中都是如此,但在 TypeScript 中更为常见,因为它具有如此多的特性。只要我能为我的用户提供更好的体验,我就可以接受。
附带说明一下,您的类型定义非常接近 Rimbu's Immutable definition
在此typescript playground我写了一个最小的不可变(递归只读)类型和一个存储不可变的存储接口。
目前我的分区存储 class 的 read() 和 write() 函数存在编译错误,我想通过正确注释类型而不是进行类型断言来解决这个错误。这是顶级定义。
interface Store<State>{
read:() => Immutable<State>
write:(state:Immutable<State>) => Immutable<State>
}
export type ImmutableObject<T> =
{
readonly [K in keyof T]: Immutable<T[K]>;
}
;
export type Immutable<T> = T extends object
? ImmutableObject<T>
: T extends string | number | boolean | null
? Readonly<T>
: never;
当我从商店派生分区子商店时,我的问题就出现了。这意味着只需使用其声明的键之一选择状态的一个子部分,然后从中创建一个商店。
这是我的草稿实现,它需要注释断言来抑制编译错误...
class BasicStorePartition<SuperState, Key extends keyof SuperState>
implements Store<SuperState[Key]>{
constructor(
readonly store: Store<SuperState>,
readonly key: Key,
) {}
//this line requires the commented type assertion in order to compile
read = () => this.store.read()[this.key] // as unknown as Immutable<SuperState[Key]>
write = (state:Immutable<SuperState[Key]>) => {
this.store.write({
...this.store.read(),
[this.key]:state
});
return this.read()
}
}
编译报错如下。我希望这些解析为相同的类型并且不知道 string
作为键来自哪里,因为在源代码中没有以这种方式注释键...
Type 'ImmutableObject<SuperState[string]>' is not assignable to type 'Immutable<SuperState[Key]>'
Type 'Immutable<SuperState>[Key]' is not assignable to type 'Immutable<SuperState[Key]>'
可以通过简单地声明类型信息来修复编译,例如...
as unknown as Immutable<SuperState[Key]>
我想解决此编译错误,以便类型解析并与预期的只读类型对齐,而无需绕过编译器。任何人都可以找到这样做的方法吗?
欢迎提出有关改进该方法的任何其他意见。
恐怕编译器无法毫无疑问地知道您希望它推断的类型是正确的,即使在实践中它们可能是正确的(在打字稿)。
以下是我对您的问题的观察:
object
类型已弃用,请参阅 this question。显然人们对它的使用有疑问。在我看来,如果您 99% 确定它是正确的,那么在您的 实现 中使用类型断言是可以的。编译器并不完美,而且永远不会。但永远不要从你的 public 接口 返回错误的类型,或者强迫你的函数的用户做断言。我遇到了很多 public 类型信息不佳或错误的库,这真的很令人沮丧。
我正在创作 Rimbu immutable collections library,其中我已尽最大努力使类型信息尽可能正确和精确。但是,如果您看起来 'under the hood' 可以这么说,代码中充满了类型断言,因为编译器,尤其是在更高级的情况下,只需要帮助。这在任何类型化语言中都是如此,但在 TypeScript 中更为常见,因为它具有如此多的特性。只要我能为我的用户提供更好的体验,我就可以接受。
附带说明一下,您的类型定义非常接近 Rimbu's Immutable definition