流程,如何从混合类型转换为更具体的类型(Flow, how to type cast to a more specific type from mixed)

编程入门 行业动态 更新时间:2024-10-25 11:33:52
流程,如何从混合类型转换为更具体的类型(Flow, how to type cast to a more specific type from mixed)

用于express的流式libdef将locals定义为具有mixed值的对象。 指定实际值类型会导致下面的错误...这些特定类型应如何注释?

// From libdef type Locals = { [name: string]: mixed; } // Populated data const locals: Locals = { version: 1.2, resources: { a: "abc", b: "def" } }; // Annotate the actual type const version: number = locals.version; // Error: mixed is incompatible with number const resources: {[string]: string} = locals.resources; // Error: mixed is incompatible with object type

The flow-typed libdef for express defines locals as an object with mixed values. Specifying the actual value types results in the errors below... how should these specific types be annotated?

// From libdef type Locals = { [name: string]: mixed; } // Populated data const locals: Locals = { version: 1.2, resources: { a: "abc", b: "def" } }; // Annotate the actual type const version: number = locals.version; // Error: mixed is incompatible with number const resources: {[string]: string} = locals.resources; // Error: mixed is incompatible with object type

最满意答案

一种方法是改进您收到的任何类型,直到它符合您要找的形状。 通常,我会创建一些基本的细化函数,并使用它们来构建更大的细化。

( 尝试 )

// From libdef type Locals = { [name: string]: mixed; } // Populated data const locals: Locals = { version: 1.2, resources: { a: "abc", b: "def" } }; // The type you want type MyLocals = { version: number, resources: { // maybe this one is a map? idk [string]: string } } // Some basic refinement functions const refineString = (x: mixed): string => { if (typeof x === 'string') { return x } throw new Error("Not a string") } const refineNumber = (x: mixed): number => { if (typeof x === 'number') { return x } throw new Error("Not a number") } const refineObj = (x: mixed): {[string]: mixed} => { if (x instanceof Object) { return x } throw new Error("Not an object") } // More type-specifc refinement functions const refineResources = (x: mixed): $ElementType<MyLocals, 'resources'> => { const anObj = refineObj(x) return Object.keys(anObj) .reduce((acc, k) => Object.assign(acc, { [k]: refineString(anObj[k]) }), {}) } const refineMyLocals = (x: mixed): MyLocals => { const {version, resources} = refineObj(x) return { version: refineNumber(version), resources: refineResources(resources) } } // Now use them to assert a type const myLocals: MyLocals = refineMyLocals(locals) const version: number = myLocals.version; const resources: {[string]: string} = myLocals.resources;

或者,如果libdef位于flow-typed文件夹中,只需进入并更改libdef即可。 它将使该类型专用于您的项目,但它可能是处理该类型的最有效方式,假设您不需要代码中其他位置的[name: string]: mixed类型。

One way is to refine the type of whatever you've recieved until it fits the shape you're looking for. Usually, I make a handful of basic refinement functions and use those to build up larger refinements.

(Try)

// From libdef type Locals = { [name: string]: mixed; } // Populated data const locals: Locals = { version: 1.2, resources: { a: "abc", b: "def" } }; // The type you want type MyLocals = { version: number, resources: { // maybe this one is a map? idk [string]: string } } // Some basic refinement functions const refineString = (x: mixed): string => { if (typeof x === 'string') { return x } throw new Error("Not a string") } const refineNumber = (x: mixed): number => { if (typeof x === 'number') { return x } throw new Error("Not a number") } const refineObj = (x: mixed): {[string]: mixed} => { if (x instanceof Object) { return x } throw new Error("Not an object") } // More type-specifc refinement functions const refineResources = (x: mixed): $ElementType<MyLocals, 'resources'> => { const anObj = refineObj(x) return Object.keys(anObj) .reduce((acc, k) => Object.assign(acc, { [k]: refineString(anObj[k]) }), {}) } const refineMyLocals = (x: mixed): MyLocals => { const {version, resources} = refineObj(x) return { version: refineNumber(version), resources: refineResources(resources) } } // Now use them to assert a type const myLocals: MyLocals = refineMyLocals(locals) const version: number = myLocals.version; const resources: {[string]: string} = myLocals.resources;

Alternatively, if the libdef is in the flow-typed folder, just go in there and change the libdef. It will make that type specific to your project, but it might be the most effective way to handle it assuming you don't need the the [name: string]: mixed type somewhere else in your code.

更多推荐

本文发布于:2023-08-06 06:33:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1446016.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:类型   转换为   流程   Flow   mixed

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!