首页 > 解决方案 > 复杂的 json 打字稿打字

问题描述

我很难理解为什么打字稿对我的 json 的输入不满意:

const myjson = { 
    "cube": {
        "points":
            [[-100, -100, -100],
             [ 100, -100, -100],
            ],
        "triangles":
            [[0,1,2,"rgba(255,255,127,0.3)"],
             [2,3,0,"rgba(255,255,127,0.3)"]
            ]
    },
    "pyramid": {
        "points":
            [[   0, -100,    0],
             [ 100,  100, -100],
            ],
        "triangles":
            [[0,1,2,"rgba(255,255,127,0.3)"],
             [0,2,3,"rgba(0,255,127,0.3)"],
            ]
    }
}

interface Data3D {
    [k: string]: {
    points: number[][];
    triangles: [number, number, number, string][];
  }
}

const make3D = (jsondata: Data3D) => {
    console.log(jsondata);
}

make3D(myjson);

打字稿抱怨三角形类型:

Types of property 'triangles' are incompatible.
        Type '(string | number)[][]' is not assignable to type '[number, number, number, string][]'.
          Type '(string | number)[]' is not assignable to type '[number, number, number, string]'.
            Target requires 4 element(s) but source may have fewer.(2345)

我使用自定义类型 [number, number, number string] 键入,但 Typescript 报告它可能包含更少的元素?

如果我将三角形的类型更改为:

triangles: (number | string)[][];

有用。

为什么我不能像那样更精确地输入它?:

triangles: [number, number, number, string][];

标签: typescripttypescript-typings

解决方案


当你说,

const myjson = { 
    "cube": {
        "points":
            [[-100, -100, -100],
             [ 100, -100, -100],
            ],
        "triangles":
            [[0,1,2,"rgba(255,255,127,0.3)"],
             [2,3,0,"rgba(255,255,127,0.3)"]
            ]
    },
    "pyramid": {
        "points":
            [[   0, -100,    0],
             [ 100,  100, -100],
            ],
        "triangles":
            [[0,1,2,"rgba(255,255,127,0.3)"],
             [0,2,3,"rgba(0,255,127,0.3)"],
            ]
    }
};

const cubeTriangle = myjson.cube.triangles[0];
// infers as 
// const cubeTriangle: (string | number)[]

myjson.cube.triangles[number]推断为(string | number)[],这是随机 JSON 的最合乎逻辑的推断。Typescript 不知道Data3D它正在查看它。所以,你需要明确告诉 TS JSON 实际上是Data3D

const myjson: Data3D = { 
    cube: {
        points:
            [[-100, -100, -100],
             [ 100, -100, -100],
            ],
        triangles:
            [[0,1,2,"rgba(255,255,127,0.3)"] ,
             [2,3,0,"rgba(255,255,127,0.3)"],
            ]
    },
    pyramid: {
        points:
            [[   0, -100,    0],
             [ 100,  100, -100],
            ],
        triangles:
            [[0,1,2,"rgba(255,255,127,0.3)"],
             [0,2,3,"rgba(0,255,127,0.3)"],
            ]
    }
};

const cubeTriangle = myjson.cube.triangles[0];
// const cubeTriangle: TriangleTuple
// if you don't create an TriangleTuple type
// it would say 
// const cubeTriangle: [number, number, number, string]
// I just like to keep readability high

type TriangleTuple = [number, number, number, string];

TS 游乐场:https ://tsplay.dev/WGk3JW


推荐阅读