gpt4 book ai didi

typescript - redux的typescript类型中CombinedState类型的原因

转载 作者:行者123 更新时间:2023-12-04 01:39:32 27 4
gpt4 key购买 nike

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;

Play

此行为称为 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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com