为什么使用 Record 类型注释此对象会删除 Intellisense?
Why does annotating this object with a Record type remove Intellisense?
我正在创建一个如下所示的数据文件:
interface ISprite {
textureName: string,
frame: Frame,
origin: Vec2,
zIndex?: number
}
export let sprites: Record<string, ISprite> = {
monster: {
textureName: "monster",
frame: new Frame(0, 0, 32, 41),
origin: new Vec2(16, 28),
zIndex: -1
},
player: {
textureName: "player",
frame: new Frame(0, 0, 32, 32),
origin: new Vec2(15, 32)
}
};
如果我然后尝试从另一个文件导入此数据文件,如下所示:
import { sprites } from "../data/sprites";
然后尝试像这样访问 属性:
let player = sprites.player;
然后我在键入 sprites.
时没有获得 Intellisense(代码完成)
但是,我注意到,如果我从 sprites
变量声明中删除 Record<string, ISprite>
注释,我 会 获得智能感知。
但是,我相信我需要这个注释,因为我的一个函数只接受 ISprite
类型,我不想让它接受 any
.
是否可以在保持强类型的同时进行代码补全?
它这样做是因为 Record<string, ISprite>
可以将 任何 字符串作为键。 UI 无法提示每个字符串。
您可以为 UI 提供更多信息,通过使用具有这些命名属性的类型与 [=14] 之间的交集,使其显示 monster
和 player
以自动完成=](但请继续阅读,您可能不需要):
export let sprites: {monster: ISprite, player: ISprite} & Record<string, ISprite> = {
// −−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
monster: {
textureName: "monster",
frame: new Frame(0, 0, 32, 41),
origin: new Vec2(16, 28),
zIndex: -1
},
player: {
textureName: "player",
frame: new Frame(0, 0, 32, 32),
origin: new Vec2(15, 32)
}
};
然而:
I believe I require this annotation, because one of my functions only takes ISprite types.
没关系。根本没有任何类型注释,您的对象在其 monster
和 player
属性上的值与 ISprite
兼容,因此您可以将它们传递给需要 ISprite
的函数。 TypeScript 的类型系统是 structural(基于对象的形状),而不是 nominal(基于类型的名称),因此它很乐意接受任何对象作为 ISprite
,只要它具有兼容类型的所有必要属性。这很好用,例如:
export let sprites = {
monster: {
textureName: "monster",
frame: new Frame(0, 0, 32, 41),
origin: new Vec2(16, 28),
zIndex: -1
},
player: {
textureName: "player",
frame: new Frame(0, 0, 32, 32),
origin: new Vec2(15, 32)
}
};
function example(sprite: ISprite) {
console.log(sprite);
}
example(sprites.monster); // <=== Perfectly happy
如果您想要类型名称,或者在 sprites
中编写更多条目时提示 ISprite
的成员,您可以给自己一个函数:
makeSprite(sprite: ISprite) {
return sprite;
}
它看起来像是什么都不做,而且在运行时确实如此。 (别担心,它并不贵)。但在创作时,它允许您这样做:
export let sprites = {
monster: makeSprite({
textureName: "monster",
frame: new Frame(0, 0, 32, 41),
origin: new Vec2(16, 28),
zIndex: -1
}),
player: makeSprite({
textureName: "player",
frame: new Frame(0, 0, 32, 32),
origin: new Vec2(15, 32)
})
};
当您添加条目时,系统会提示您输入 ISprite
中的 属性 个名称,同时您正在为 makeSprite
编写 sprite 参数。
我正在创建一个如下所示的数据文件:
interface ISprite {
textureName: string,
frame: Frame,
origin: Vec2,
zIndex?: number
}
export let sprites: Record<string, ISprite> = {
monster: {
textureName: "monster",
frame: new Frame(0, 0, 32, 41),
origin: new Vec2(16, 28),
zIndex: -1
},
player: {
textureName: "player",
frame: new Frame(0, 0, 32, 32),
origin: new Vec2(15, 32)
}
};
如果我然后尝试从另一个文件导入此数据文件,如下所示:
import { sprites } from "../data/sprites";
然后尝试像这样访问 属性:
let player = sprites.player;
然后我在键入 sprites.
但是,我注意到,如果我从 sprites
变量声明中删除 Record<string, ISprite>
注释,我 会 获得智能感知。
但是,我相信我需要这个注释,因为我的一个函数只接受 ISprite
类型,我不想让它接受 any
.
是否可以在保持强类型的同时进行代码补全?
它这样做是因为 Record<string, ISprite>
可以将 任何 字符串作为键。 UI 无法提示每个字符串。
您可以为 UI 提供更多信息,通过使用具有这些命名属性的类型与 [=14] 之间的交集,使其显示 monster
和 player
以自动完成=](但请继续阅读,您可能不需要):
export let sprites: {monster: ISprite, player: ISprite} & Record<string, ISprite> = {
// −−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
monster: {
textureName: "monster",
frame: new Frame(0, 0, 32, 41),
origin: new Vec2(16, 28),
zIndex: -1
},
player: {
textureName: "player",
frame: new Frame(0, 0, 32, 32),
origin: new Vec2(15, 32)
}
};
然而:
I believe I require this annotation, because one of my functions only takes ISprite types.
没关系。根本没有任何类型注释,您的对象在其 monster
和 player
属性上的值与 ISprite
兼容,因此您可以将它们传递给需要 ISprite
的函数。 TypeScript 的类型系统是 structural(基于对象的形状),而不是 nominal(基于类型的名称),因此它很乐意接受任何对象作为 ISprite
,只要它具有兼容类型的所有必要属性。这很好用,例如:
export let sprites = {
monster: {
textureName: "monster",
frame: new Frame(0, 0, 32, 41),
origin: new Vec2(16, 28),
zIndex: -1
},
player: {
textureName: "player",
frame: new Frame(0, 0, 32, 32),
origin: new Vec2(15, 32)
}
};
function example(sprite: ISprite) {
console.log(sprite);
}
example(sprites.monster); // <=== Perfectly happy
如果您想要类型名称,或者在 sprites
中编写更多条目时提示 ISprite
的成员,您可以给自己一个函数:
makeSprite(sprite: ISprite) {
return sprite;
}
它看起来像是什么都不做,而且在运行时确实如此。 (别担心,它并不贵)。但在创作时,它允许您这样做:
export let sprites = {
monster: makeSprite({
textureName: "monster",
frame: new Frame(0, 0, 32, 41),
origin: new Vec2(16, 28),
zIndex: -1
}),
player: makeSprite({
textureName: "player",
frame: new Frame(0, 0, 32, 32),
origin: new Vec2(15, 32)
})
};
当您添加条目时,系统会提示您输入 ISprite
中的 属性 个名称,同时您正在为 makeSprite
编写 sprite 参数。