我正在为外部库编写 Typescript 模块。
这是我的一段 index.d.ts
declare module 'my-external-library' {
export class MyComponent extends React.Component<MyComponentProps> {}
export class CustomClass {
constructor(
firstParam: string,
secondParam: string,
)
}
interface MyComponentProps {
config: string
customClass: CustomClass
text?: string
customFn?: (input: string) => boolean
}
}
除了 customClass
Prop 外,这工作正常。
自定义类是一个类,必须是这样的:
class customClass {
constructor(firstParam, secondParam) {
this.firstParam = firstParam
this.secondParam = secondParam
}
... all the methods you want
}
export default customClass
在一个单独的文件中,我将 customClass
属性提供给 MyComponent
,如下所示:
import customClass from './customClass'
<MyComponent
config: "test"
customClass: customClass
/>
customClass
实际上没有收到在 index.d.ts
中声明的“构造函数类型”,但组件的所有其他属性都运行良好。
那么,我所做的类定义是正确的吗?我必须用另一种方法导出类吗?
这是一个 CodeSandbox:https://codesandbox.io/s/react-typescript-playground-forked-nrfk2
感谢大家的帮助,见谅
最佳答案
我已经 fork 并编辑了你的代码沙箱,检查一下:
现在我要解释一下 typescript 中关于类的一些东西,这确实很令人困惑。
部分原因是人们使用术语“类”来指代差异上下文中的差异事物。为了消除歧义,让我们使用更准确的术语。
构造函数
MyPuppy
通常被称为“类”,但在 JS 术语中它也是一个“构造函数”。因此,让我们在整个讨论中坚持构造函数。
// javascript
class MyPuppy {}
实例
变量 puppy
是 MyPuppet
的实例
// javascript
const puppy = new MyPuppet()
实例类型与构造函数类型
在 typescript 中,当您声明如下所示的类时,您将隐式声明一个同名的实例类型!
这种行为让很多人感到困惑。简而言之,MyPuppy
作为一个 JS 变量 包含一个构造函数,而 MyPuppy
作为一个 TS 类型变量 实际上拥有一个实例类型。
现在我们如何引用MyPuppy
构造函数的类型,也就是构造函数类型?您应该按字面意义使用 typeof MyPuppy
。
// typescript
class MyPuppet {}
type MyPuppetInstance = MyPuppet
type MyPuppetConstructor = typeof MyPuppet
我们已经消除了术语歧义,让我们来做一些案例研究。
有一个类的“实例端”和“静态端”的概念,曾经记录在 old TS handbook 中。 .基本上“实例端”对应于实例类型,“静态端”对应于构造函数类型。
class MyPuppy {
static getSpecies(dog: MyPuppy) {
return dog.species
}
constructor(species: string) { this.species = species }
species: string
// [side note] above two lines can be combined as one:
// constructor(public species: string) {}
poop() { return '💩' }
}
type MyPuppetInstance = MyPuppet
type MyPuppetConstructor = typeof MyPuppet
var bar: MyPuppetConstructor = MyPuppy
var foo: MyPuppetInstance = new bar("shiba_inu")
上面的代码片段做了几件事。
- 声明一个名为
MyPuppy
的 JS 构造函数。 - 隐式声明一个 TS 实例类型
MyPuppy
。 - 在“实例端”,
foo
是一个实例,并且有一个属性species
和一个方法poop
. - 在“静态”方面,
bar
是一个构造函数,它是一个“可更新的函数”,可以作为new bar("shiba_inu")
,还有一个静态方法getSpecies
。
现在在.d.ts
文件中,我们如何声明上述类型?您可以使用 interface
关键字或 type
关键字。它们几乎没有区别。
// index.d.ts
interface MyPuppyInstance {
species: string
poop(): string
}
interface MyPuppyConstructor {
new (species: string): MyPuppyInstance
getSpecies(dog: { species: string }): string
}
type MyPuppyInstance2 = {
species: string
poop(): string
}
type MyPuppyConstructor2 =
(new (species: string) => MyPuppyInstance)
& { getSpecies(dog: { species: string }): string }
关于javascript - 在 Typescript 模块中定义类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68950088/