【问题标题】:How to resolve typescript error for topojson package?如何解决 topojson 包的打字稿错误?
【发布时间】:2020-02-23 22:00:46
【问题描述】:

请原谅这个幼稚的问题;我是打字稿的新手。在 javascript 中,我可以使用topojson.mesh 来创建这样的网格对象:

import us from "./counties-albers-10m.json"
topojson.mesh(us, us.objects.states, (a, b) => a !== b))

当我尝试在 Typescript 中执行此操作时,我收到以下警告:

Types of property 'type' are incompatible. Type 'string' is not assignable to type "Topology" TS2345

我也安装了@types/topojson。谁能帮我调试一下?我对打字稿的了解还不够,无法理解问题所在。

更广泛地说,如何调试这样的错误?我发现 3rd 方包存在各种类型问题,并且在很多情况下不知道如何为我的 javascript 对象分配正确的类型。感谢您的帮助。

【问题讨论】:

  • 请提供一个最小的 git repo 用于调试
  • 使用 typescript 不应产生与使用 js 不同的输出。如果您有编译问题,您应该提供正在使用的包的所有版本(pacakge.json)。此外,如果您使用 IDE/编辑器进行动态编译,通常不会有相同的配置。

标签: typescript topojson


【解决方案1】:

一旦我安装了@types/topojson,我就可以像这样从topojson-specification 导入所需的类型:

import * as topojson from 'topojson-client';
import { GeometryObject, Topology } from 'topojson-specification';
import us from '../counties-albers-10m.json';

topojson.mesh(
  (us as unknown) as Topology,
  us.objects.states as GeometryObject,
  (a: GeometryObject, b: GeometryObject) => a !== b
);

更广泛地说,如何调试这样的错误?

为了调试这种东西,我使用我的 IDE(VS 代码)来检查方法,比如 .mesh 方法,并查看它所期望的类型。我还使用了 Go To Definition 功能(⌘ + 单击 Mac)来查看类型定义:

转到类型定义文件还向我展示了他们从哪里导入类型。

虽然有一部分我无法弄清楚。当您在 TypeScript 中导入 JSON 时,它会自动推断类型,但这些自动类型似乎与 @types/topojson 的类型冲突,原因有很多(例如 number[] !== [number, number])。这就是为什么我需要先转换为unknown,然后再转换为正确的类型。这可能不是最佳解决方案,但我不知道如何描述 JSON 文件的类型。

【讨论】:

    【解决方案2】:

    谁能帮我调试一下?

    错误基本上说:

    您从"./counties-albers-10m.json" 传入的us 对象文字的属性type 具有string 类型,但来自@types/topojson 的类型预计它是string literal type @987654331 @,它比扩展的 string 更具体。例如,您不能这样做:

    const wideString: string = "something"
    const stringLiteral: "Topology" = wideString // error, string not assignable to type "Topology"
    

    在检查mesh 的类型及其第一个函数参数topology 类型为Topology 时,您确实可以看到,类型与上面确定的完全相同。

    那是为什么呢?我们来看一个简单的 JSON 文件:

    { "a": "foo", "b": 42 }
    

    当用import us from "./counties-albers-10m.json" 导入这个文件时,us 的类型实际上是:

    type US = typeof us; // type US = { a: string; b: number; }
    

    TypeScript 扩展从 JSON 文件推断的属性文字类型"foo" 分别变为 string42 分别变为 number。这种行为是intentional,但还有一个功能请求要求more flexbilityas const 为您提供狭窄、精确的类型。

    解决方案

    使用类型断言 (as) 将导入的 us 对象转换为 Topology 或自定义类型。

    import { Topology } from "topojson-specification" // needed type for mesh API
    // alternatively use a custom compatible json type
    
    import us_ from "./counties-albers-10m.json"
    
    const us: Topology = us_ as Topology; 
    
    topojson.mesh(us, ...) // this should work now
    

    如何调试这样的错误?

    错误消息非常有用,我认为您只是不知道字符串文字类型和/或 JSON 扩展。一般来说,您还可以使用 VS Code 之类的 IDE 查看第三种库类型,以查看预期的形状。

    【讨论】:

    • 感谢您的帮助和解释。这很有帮助!我遇到的一个问题是当我import us_ from "./counties-albers-10m.json" 并尝试生成const us: Topology = us_ as Topology; 时,TS 说:type 'Topology<Objects<GeoJsonProperties>>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. The types of 'transform.scale' are incompatible between these types. Type 'number[]' is missing the following properties from type '[number, number]': 0, 1 TS2352。有什么想法吗?
    • 这是怎么回事:我们通过as将导入的us_ json 对象“投射”到Topology。这种类型断言粗略检查us 是否真的属于您想要的Topology 类型 - 如果us 可分配给Topology Topology 是否可分配给us ,那么编译器认为你的断言是有效的。所以这取决于你保存在"./counties-albers-10m.json"中的数据结构。如果它看起来像 Topology,它应该与 as 一起使用。如果你确定一切都很好,你可以使用硬类型断言const us = us_ as unknown as Topology 来禁用所有检查。
    猜你喜欢
    • 2021-01-08
    • 1970-01-01
    • 2019-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-19
    • 1970-01-01
    • 2020-11-24
    相关资源
    最近更新 更多