javascript - 在 Typescript 模块中定义类

标签 javascript typescript types

我正在为外部库编写 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 并编辑了你的代码沙箱,检查一下:

Edit React Typescript Playground (forked)

现在我要解释一下 typescript 中关于类的一些东西,这确实很令人困惑。

部分原因是人们使用术语“类”来指代差异上下文中的差异事物。为了消除歧义,让我们使用更准确的术语。

构造函数

MyPuppy 通常被称为“类”,但在 JS 术语中它也是一个“构造函数”。因此,让我们在整个讨论中坚持构造函数

// javascript
class MyPuppy {}

实例

变量 puppyMyPuppet实例

// 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")

上面的代码片段做了几件事。

  1. 声明一个名为 MyPuppy 的 JS 构造函数
  2. 隐式声明一个 TS 实例类型 MyPuppy
  3. 在“实例端”,foo 是一个实例,并且有一个属性species 和一个方法poop.
  4. 在“静态”方面,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/

相关文章:

javascript - 属性值中的连字符导致 AngularJs 验证中断

javascript - 为什么带有对象的 typeof 数组返回 "object"而不是 "array"?

javascript - react : Using ES6 component in TS component: TS2605: JSX element type 'xxx' is not a constructor function for JSX elements

scala - 迷失在 Scala 集合的继承图中

c - 通过指针递增读取作为 void* 传递的 char 数组,然后读取为 char 和其他数据类型?

javascript - jqplot:如果我有两个饼图,我可以使具有相同标签的每个楔形具有相同的颜色吗?

javascript - 如何点击 p :commandButton using javascript

typescript - TSLint:禁止使用 Function.length 属性

typescript - 从 Inno Setup 中的文本文件读取应用程序版本

c++ - std::function 带模板,类型问题,没有匹配的调用函数