- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Redux 有以下几种类型:
declare const $CombinedState: unique symbol
/**
* State base type for reducers created with `combineReducers()`.
*
* This type allows the `createStore()` method to infer which levels of the
* preloaded state can be partial.
*
* Because Typescript is really duck-typed, a type needs to have some
* identifying property to differentiate it from other types with matching
* prototypes for type checking purposes. That's why this type has the
* `$CombinedState` symbol property. Without the property, this type would
* match any object. The symbol doesn't really exist because it's an internal
* (i.e. not exported), and internally we never check its value. Since it's a
* symbol property, it's not expected to be unumerable, and the value is
* typed as always undefined, so its never expected to have a meaningful
* value anyway. It just makes this type distinquishable from plain `{}`.
*/
export type CombinedState<S> = { readonly [$CombinedState]?: undefined } & S
对于这个符号和类型的用途,我有点一头雾水。
示例用法在combineReducers
export default function combineReducers<S>(
reducers: ReducersMapObject<S, any>
): Reducer<CombinedState<S>>
export default function combineReducers<S, A extends Action = AnyAction>(
reducers: ReducersMapObject<S, A>
): Reducer<CombinedState<S>, A>
export default function combineReducers<M extends ReducersMapObject<any, any>>(
reducers: M
): Reducer<
CombinedState<StateFromReducersMapObject<M>>,
ActionFromReducersMapObject<M>
>
export default function combineReducers(reducers: ReducersMapObject) {
const reducerKeys = Object.keys(reducers)
const finalReducers: ReducersMapObject = {}
for (let i = 0; i < reducerKeys.length; i++) {
const key = reducerKeys[i]
if (process.env.NODE_ENV !== 'production') {
if (typeof reducers[key] === 'undefined') {
warning(`No reducer provided for key "${key}"`)
}
}
if (typeof reducers[key] === 'function') {
finalReducers[key] = reducers[key]
}
}
评论说它曾经将它与 {}
或空类型区分开来,但我在任何地方都看不到它检查这种类型,甚至在评论中说我们在内部从不检查它的值那么为什么它甚至在那里除了让像我这样的人感到困惑之外?
最佳答案
正如评论中提到的 typescript 是鸭子类型的,这意味着您可以将看似无关的类型分配给另一个:
type A = { foo: string, baz?: string }
type B = { foo: string, goo?: number }
declare let a: A;
declare let b: B;
// Unrelated types, structurally compatible, so assignable
a = b;
b = a;
此行为称为 structural typing并且不同于其他强类型语言(例如 Java 或 C#)的工作方式。更多传统语言使用nominal typing ,其中结构无关紧要,并且,除了一些继承关系,A
不会分配给 B
。
为了在 typescript 中模拟类似于名义打字的东西,我们可以使用私有(private)字段或 unique symbol
,它们确实表现得名义上。这意味着结构无关紧要,在决定兼容性时,两个 unique symbol
只有来自相同的定义才兼容。
这意味着对于 CombinedState
,类型系统将能够保证如果类型 T extends { [$CombinedState]: undefined }
它一定已经到来来自 combineReducers
(或者至少它是 CombinedState
的实例)。这是有保证的,因为客户端无法访问 $CombinedState
,因此它只能在库中使用。
为什么这很重要?好吧,可能是因为 PreloadedState
:
/**
* Recursively makes combined state objects partial. Only combined state _root
* objects_ (i.e. the generated higher level object with keys mapping to
* individual reducers) are partial.
*/
export type PreloadedState<S> = Required<S> extends {
[$CombinedState]: undefined
}
? S extends CombinedState<infer S1>
? {
[K in keyof S1]?: S1[K] extends object ? PreloadedState<S1[K]> : S1[K]
}
: never
: {
[K in keyof S]: S[K] extends object ? PreloadedState<S[K]> : S[K]
}
在 PreloadedState
中,S
是一个 CombinedState
这一事实在条件类型中触发了不同的行为。
关于typescript - redux的typescript类型中CombinedState类型的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58046899/
我已经使用 npm 安装了 react-admin 并在构建之后, 我收到此错误: node_modules/redux/index:没有导出成员“CombinedState”。 TS2694 它链接
嗨,我正在尝试让 redux 坚持使用 redux 工具包(也在 typescript 中)我收到以下错误: 导出的变量“store”具有或正在使用来自外部模块“home/..../node_modu
我是一名优秀的程序员,十分优秀!