Pixi.js: 需要帮助:TypeScript 转换更新

创建于 2020-02-01  ·  24评论  ·  资料来源: pixijs/pixi.js

你好 PixiJS 社区,

通过转换核心及其所有依赖项,我们在将 PixiJS 转换为 TypeScript 方面达到了一个重要里程碑。 现在我们已经克服了这个难题,我们可以从依赖于这一小部分核心包的其余包开始。

我们绝对可以使用开发人员的手来转换这些包的其余部分。 如果您有兴趣转换包裹,请告诉我是哪一个。 有一些转换包的指南,您可以从现有的已完成 PR 中看到。

转换 Gotchyas

  • 我们试图维护 JSDocs 直到一切都完成,然后转换为 Typedoc 并在之后发出类型。 我们要求您维护 JSDocs 并确保它们仍然通过npm run docs正确构建和显示
  • 请使用git mv将 JS 文件重命名为 TS,否则我们会丢失 Git 历史记录。 一些 Git GUI 可能不会接受这些更改。
  • 请不要将public访问修饰符添加到仅限内部的方法或成员,在这些情况下不要定义访问。

套餐

要索取包裹,请为其创建草稿 PR

  • [x] @pixi/accessibility #6379
  • [x] @pixi/app #6376
  • [x] @pixi/constants #6173
  • [x] @pixi/core #6340, #6373
  • [x] @pixi/display #6261、#6339、#6349、#6371
  • [x] @pixi/extract #6381
  • [x] @pixi/graphics #6352
  • [x] @pixi/interaction #6656
  • [x] @pixi/loaders #6385
  • [x] @pixi/math #6141
  • [x] @pixi/mesh-extras #6396
  • [x] @pixi/mesh #6382
  • [x] @pixi/mixin-cache-as-bitmap #6630
  • [x] @pixi/mixin-get-child-by-name #6621
  • [x] @pixi/mixin-get-global-position #6637
  • [x] @pixi/particles #6449
  • [x] @pixi/polyfill #6654, #6669
  • [x] @pixi/prepare #6481
  • [x] @pixi/runner #6164
  • [x] @pixi/settings #6315
  • [x] @pixi/sprite-animated #6397
  • [x] @pixi/sprite-tiling #6398
  • [x] @pixi/sprite #6375
  • [x] @pixi/spritesheet #6389
  • [x] @pixi/text-bitmap #6479
  • [x] @pixi/text #6390
  • [x] @pixi/ticker #6186
  • [x] @pixi/unsafe-eval #6655
  • [x] @pixi/utils #6262
  • [x] @pixi/canvas-display #6659
  • [x] @pixi/canvas-extract #6503
  • [x] @pixi/canvas-graphics #6663
  • [x] @pixi/canvas-mesh #6664
  • [x] @pixi/canvas-particles #6622
  • [x] @pixi/canvas-prepare #6657
  • [x] @pixi/canvas-renderer #6499
  • [x] @pixi/canvas-sprite-tiling #6665
  • [x] @pixi/canvas-sprite #6658
  • [x] @pixi/canvas-text #6666
  • [x] @pixi/filter-alpha #6383
  • [x] @pixi/filter-blur #6383
  • [x] @pixi/filter-color-matrix #6383
  • [x] @pixi/filter-displacement #6383
  • [x] @pixi/filter-fxaa #6383
  • [x] @pixi/filter-noise #6383

捆绑

  • [ ] pixi.js-legacy #6673进行中@bigtimebuddy
  • [ ] pixi.js #6673进行中@bigtimebuddy

最有用的评论

我讨厌更改 API 以适应打字限制,只是我觉得不合适。 就个人而言,我宁愿使用 any 然后创建一个新方法。 拥有如此大的 API 表面已经是一种负担。

所有24条评论

更多提示:

  • 尝试将所有额外的import (实际上是它的导入类型)与现有导入分开。 当新的 TS 版本推出时,我们将添加import type 。 但是 linter 会阻止您使用同一模块中的两行import ,在这种情况下混合使用它们很好。

  • 你可以同时使用Array<X>X[]符号,我通常使用Array<X>来表示经常被推送的结构(又名列表)。 X[]用于具有固定小长度的事物,或者如果大小是在构造它们的相同位置决定的(常规数组)。

  • 如果readonly字段仅在destroy()中更改 - 您可以在那里使用any转换。 如果它在其他地方使用 - 删除readonly 。 我们可以稍后决定是否将其设为private field + readonly property

这个周末我可以做@pixi-text ,除非有人打败我。

注意:@pixi-tiling 将有PIXI.TilingSprite.from哪个晚上在 TS 中是不可能的。 我们可以弃用它。

去吧,@qtiki。 周末我会在线,以防你发现奇怪的事情。

好的, @qtiki ,您的选择将在发送 PR 草案后保留。
谢谢!

同意。 PR 草案是声明要转换的包的最佳方式。 感谢您的帮助

好的, @qtiki ,您的选择将在发送 PR 草案后保留。
谢谢!

我打开了 PR #6390 草案。 我刚刚将 .js 文件重命名为 .ts 以进行一些更改以创建 PR。 我将在本周末尝试进行实际转换。

我在将 Text 包转换为 TypeScript 时遇到的一些通用问题:

所以我遇到了 TypeScript 属性的基本问题。 似乎 TypeScript 不支持属性 getter 和 setter 的不同类型: https ://github.com/microsoft/TypeScript/issues/2521

在 Text 和 TextStyle 类中的某些地方,这将是一个巨大的好处。 例如,TextStyle 中的fillStylestroke接受一个数字,然后将其转换为字符串,因此 getter 不应返回带有数字的联合类型。 现在它返回一个带有数字的联合类型,我必须将其转换为能够将其传递给 CanvasRenderingContext2D fillStyle

Text 类本身也接受具有文本样式的对象,然后将其传递给new TextStyle - 或直接传递给 TextStyle 的实例。 同样在这里,getter 将始终返回一个 TextStyle 实例,但必须使用与 setter 相同的联合类型来键入。 所以这将导致用户空间中一些不必要的类型检查(或强制转换)能够调用 TextStyle 的方法。

从长远来看,我真的不知道什么是最好的解决方案,但现在我想这将不得不做。

我注意到的另一件事是,有相当多的代码重用了不同类型的局部变量,这在 TypeScript 中表现不佳。 我不想过多地触及现有代码,所以我只是使用联合类型和一些丑陋的强制转换来编译它。 我想随着时间的推移,童子军原则可以改善这些事情。

@qtiki
为什么你在这个主题中写问题而不是你的 PR?

@qtiki
为什么你在这个主题中写问题而不是你的 PR?

我相信这些是人们在使用 TypeScript 转换时会遇到的一般问题,而不仅仅是文本包特定的问题。 如果要正确键入它们,则属性问题是未来的基本设计问题。

自从遇到 TypeScript 设置器和获取器后,我一直在研究无法使用不同类型的问题。 看来这个问题是一个非常复杂的问题,它可能永远不会得到“修复”。 因此,这是我对将这些类型的属性转换为 TypeScript 的一般准则的建议:

这是我们想要的一个简化示例:一个接受string | number但在内部存储(并返回)为string的属性。 自然地,我们可以将属性返回为string | number ,但这意味着 API 的用户将面临完全不必要的类型检查。

class Foo {
    constructor() {
        this._bar = '';
    }

    // error: 'get' and 'set' accessor must have the same type.(2380)
    get bar(): string {
        return this._bar;
    }

    // error: 'get' and 'set' accessor must have the same type.(2380)
    set bar(value: string | number) {
        this._bar = value.toString();
    }

    private _bar: string;
}

以下是我们如何解决这个问题:

class Foo {
    constructor() {
        this._bar = '';
    }

    // Return the strictest type possible in the getter.
    get bar(): string {
        return this._bar;
    }

    // Use the same strict type for the setter as the getter.
    set bar(value: string) {
        // Call the conversion function.
        this.setBar(value);
    }

    // Implement a separate conversion function that accepts all supported types.
    public setBar(value: number | string) {
        this._bar = value.toString();
    }

    private _bar: string;
}

这样,用户在读取属性时可以获得正确的类型。 想要将number分配给 $ bar的 TypeScript 用户需要调用setBar转换函数。 然而,对于现有的 JavaScript 用户来说,这不会是一个重大更改,因为属性设置器调用转换函数——这意味着无类型的属性设置器确实接受数字。

大家怎么看,这有意义吗? 我不确定这种模式的使用频率,但至少在文本包中我不止一次遇到过它。

我讨厌更改 API 以适应打字限制,只是我觉得不合适。 就个人而言,我宁愿使用 any 然后创建一个新方法。 拥有如此大的 API 表面已经是一种负担。

我永远不会批准使用 set* 方法的 hack,同意@bigtimebuddy的观点,即any类型比set*方法更友好。

在当前情况下,getter 返回(string | number)类型是完全可以接受的。

实际上,由于set的继承问题,有时setBar是一个好主意,但在前缀中需要更多符号,例如_$setBar() :) 但在这种情况下不是。

@qtiki感谢您强调这个问题,我在为我的工作项目制作 pixjs ts fork 时遇到了很多次。

是的, Text是痛苦的。 是的,我们必须考虑更多。

我同意setBar不是最漂亮的解决方案。 老实说,我很惊讶 TypeScript 不支持这种类型强制的设置器。 只是一个警告,尽管对于 TypeScript 的流控制,使用更宽松的类型甚至any的这些属性意味着什么:

class Foo {
    constructor() {
        this._bar = '';
    }

    get bar(): string | number {
        return this._bar;
    }

    set bar(value: string | number) {
        this._bar = value.toString();
    }

    private _bar: string;
}

const foo = new Foo();

// TypeScript's flow control will assume from now on that `bar` is a `number`
foo.bar = 42;

function add(a: number, b: number) {
    return a + b;
}

// Call to `add` shouldn't be allowed since the value in `bar` is actually a string
// This will print `4242` instead of `84`
console.log(add(foo.bar, 42));

我认为从长远来看,最干净的选择是使用这样的东西:

class Bar {
    constructor() {
        this._bar = '';
    }

    get(): string {
        return this._bar;
    }

    set(value: string | number) {
        this._bar = value.toString();
    }

    private _bar: string;
}

class Foo {
    constructor() {
        this.bar = new Bar();
    }

    public bar: Bar;
}

const foo = new Foo();
foo.bar.set(42);
console.log(foo.bar.get());

这种类型的set并非没有先例,因为它正是PIXI.Point的实现方式。 基本上所有面向用户的 api 都可能会“按原样”接受Bar实例,而不必在任何地方手动调用get

当然,这将是一个突破性的变化,所以不会在不久的将来发生,我只想投入两分钱。

而且我刚刚意识到我之前的建议将不再是“真正的”属性,因此像Object.assign这样的东西将不再适用于 setter。 所以也许毕竟不是最好的主意。

嘿,我是 PixiJS 的长期用户和 Typescript 的用户。 我可以为此做出贡献 - 看起来大部分软件包都已经完成了。 除了帆布的。 有什么我可以帮忙的吗?

@lloydevans是的! 想做准备或文本位图? 两者都很好,希望不是超级复杂的软件包。

@bigtimebuddy太棒了! 我可以看看做文本位图。

听起来不错! 请在开始后制作 PR 草案,以便我们在此处进行跟踪。

好的,我会做。 我现在将查看一些现有的转换和 PR,并将效仿。

似乎 npm 中的各个包仍然没有类型。 我猜这是在这个问题完成后可以解决的问题? 如果能够在不牺牲类型安全性的情况下使用它们来减小构建尺寸,那就太好了。

家舒展大家! 只剩一两包了!

非常感谢 @ Zyie 、@ ivanpopelyshev 、@SerG-Y、@ eXponenta和所有其他帮助实现迁移的贡献者。

此页面是否有帮助?
0 / 5 - 0 等级