用于表达的流式类型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
答案 0 :(得分:1)
看起来这里唯一的方法是添加refinement逻辑。
(option1|option2)
请注意,您也可以自行投射数据:
if (typeof locals.version === "number") {
const version: number = locals.version;
}
if (locals.resources instanceof Object) {
const resources: {[string]: string} = locals.resources;
}
或定义新副本:
const version: number = Number(locals.version);
答案 1 :(得分:1)
一种方法是改进你收到的任何类型,直到它符合你正在寻找的形状。通常,我会制作一些基本的细化函数,并使用它们来构建更大的细化。
(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;
或者,如果libdef位于flow-typed
文件夹中,只需进入并更改libdef即可。它会使该类型特定于您的项目,但它可能是处理它的最有效方法,假设您不需要代码中其他位置的[name: string]: mixed
类型。