admin管理员组

文章数量:1122846

I have the following setup in TypeScript:

// complex.ts
export type ComplexInput = { real: number, imag: number }

export class Complex {
  constructor(value: ComplexInput) {
    // …
  }
}
// index.ts
import { Complex, type ComplexInput } from './complex.ts'

const input: ComplexInput = {
  real: 3,
  imag: -2,
}

const complex = new Complex(input)

This works fine, but I want to define the ComplexInput type inside the class so that it's scoped to the class and can be referenced as something like Complex.Input. Ideally, I would like to achieve something like this:

// complex.ts
export class Complex {
  type Input = { real: number, imag: number } // Hypothetical syntax
  constructor(value: Complex.Input) {
    // …
  }
}
// index.ts
import { Complex } from './complex.ts'

const input: Complex.Input = {
  real: 3,
  imag: -2,
}

const complex = new Complex(input)

Since type declarations aren't allowed directly inside a class, how can I achieve this behavior while keeping the type definition closely associated with the class? Is there a recommended way to encapsulate such types within a class in TypeScript?

I have the following setup in TypeScript:

// complex.ts
export type ComplexInput = { real: number, imag: number }

export class Complex {
  constructor(value: ComplexInput) {
    // …
  }
}
// index.ts
import { Complex, type ComplexInput } from './complex.ts'

const input: ComplexInput = {
  real: 3,
  imag: -2,
}

const complex = new Complex(input)

This works fine, but I want to define the ComplexInput type inside the class so that it's scoped to the class and can be referenced as something like Complex.Input. Ideally, I would like to achieve something like this:

// complex.ts
export class Complex {
  type Input = { real: number, imag: number } // Hypothetical syntax
  constructor(value: Complex.Input) {
    // …
  }
}
// index.ts
import { Complex } from './complex.ts'

const input: Complex.Input = {
  real: 3,
  imag: -2,
}

const complex = new Complex(input)

Since type declarations aren't allowed directly inside a class, how can I achieve this behavior while keeping the type definition closely associated with the class? Is there a recommended way to encapsulate such types within a class in TypeScript?

Share Improve this question edited Nov 22, 2024 at 18:50 Yukulélé asked Nov 22, 2024 at 18:41 YukuléléYukulélé 17k11 gold badges76 silver badges102 bronze badges 2
  • 3 You could merge a namespace with the class, as shown in this playground link. Does that fully address the question? If so I'll write an answer or find a duplicate; if not, what's missing? – jcalz Commented Nov 22, 2024 at 19:11
  • Yes ! that fully address my question ! I'd also like to know if this is something that's often used and if it's a good practice. My linter discourages the use of the namespace. Should I follow its advice or ignore it? – Yukulélé Commented Dec 5, 2024 at 19:09
Add a comment  | 

1 Answer 1

Reset to default 1

Allowing type aliases inside a class is a missing feature of TypeScript, requested at microsoft/TypeScript#7061. Until and unless this is implemented (and although it has a few hundred upvote I don't see any indication that it ever will be) you can work around it with declaration merging. If you want Complex.Input to be a type, you're effectively using Complex as a namespace. So you can declare it as such and TypeScript will merge them automatically:

export declare namespace Complex {
    export type Input = { real: number, imag: number }
}

export class Complex {
    constructor(value: Complex.Input) {
        // …
    }
}

This workaround is mentioned in microsoft/TypeScript#7061 by the TypeScript team dev lead as being neither "terribly great" nor "horrible". It doesn't see to be very common to do this, but it's not bad practice either.

I can't really speak authoritatively about whether or not you should care about linter rules like @typescript-eslint/no-namespace, as it is subjective. In my opinion the argument against namespace is that it's an older alternative to JavaScipt modules. But declare namespace Complex doesn't create any runtime code; it's fully erased with the rest of the type system... so it's not necessarily in violation. There's no "TypeScript internal module" at runtime that you'd be encouraged to replace with a JavaScript module. You might want to enable the allowDeclarations option so that namespaces are only flagged if you're using them to generate runtime code. But again, this part is opinion and others might disagree without anyone being objectively correct.

Playground link to code

本文标签: typingAdd static type to a class in typescriptStack Overflow