你好 PixiJS 社区,
通过转换核心及其所有依赖项,我们在将 PixiJS 转换为 TypeScript 方面达到了一个重要里程碑。 现在我们已经克服了这个难题,我们可以从依赖于这一小部分核心包的其余包开始。
我们绝对可以使用开发人员的手来转换这些包的其余部分。 如果您有兴趣转换包裹,请告诉我是哪一个。 有一些转换包的指南,您可以从现有的已完成 PR 中看到。
转换 Gotchyas
npm run docs
正确构建和显示git mv
将 JS 文件重命名为 TS,否则我们会丢失 Git 历史记录。 一些 Git GUI 可能不会接受这些更改。public
访问修饰符添加到仅限内部的方法或成员,在这些情况下不要定义访问。要索取包裹,请为其创建草稿 PR
@pixi/accessibility
#6379@pixi/app
#6376@pixi/constants
#6173@pixi/core
#6340, #6373@pixi/display
#6261、#6339、#6349、#6371@pixi/extract
#6381@pixi/graphics
#6352@pixi/interaction
#6656@pixi/loaders
#6385@pixi/math
#6141@pixi/mesh-extras
#6396@pixi/mesh
#6382@pixi/mixin-cache-as-bitmap
#6630@pixi/mixin-get-child-by-name
#6621@pixi/mixin-get-global-position
#6637@pixi/particles
#6449@pixi/polyfill
#6654, #6669@pixi/prepare
#6481@pixi/runner
#6164@pixi/settings
#6315@pixi/sprite-animated
#6397@pixi/sprite-tiling
#6398@pixi/sprite
#6375@pixi/spritesheet
#6389@pixi/text-bitmap
#6479@pixi/text
#6390@pixi/ticker
#6186@pixi/unsafe-eval
#6655@pixi/utils
#6262@pixi/canvas-display
#6659@pixi/canvas-extract
#6503@pixi/canvas-graphics
#6663@pixi/canvas-mesh
#6664@pixi/canvas-particles
#6622@pixi/canvas-prepare
#6657@pixi/canvas-renderer
#6499@pixi/canvas-sprite-tiling
#6665@pixi/canvas-sprite
#6658@pixi/canvas-text
#6666@pixi/filter-alpha
#6383@pixi/filter-blur
#6383@pixi/filter-color-matrix
#6383@pixi/filter-displacement
#6383@pixi/filter-fxaa
#6383@pixi/filter-noise
#6383pixi.js-legacy
#6673进行中@bigtimebuddypixi.js
#6673进行中@bigtimebuddy更多提示:
尝试将所有额外的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 中的fillStyle
和stroke
接受一个数字,然后将其转换为字符串,因此 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和所有其他帮助实现迁移的贡献者。
最有用的评论
我讨厌更改 API 以适应打字限制,只是我觉得不合适。 就个人而言,我宁愿使用 any 然后创建一个新方法。 拥有如此大的 API 表面已经是一种负担。