我在 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)
这工作得很好,但我想在类中定义
ComplexInput
类型,以便它的范围仅限于类,并且可以像 Complex.Input
一样被引用。理想情况下,我希望实现这样的目标:
// 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)
由于 type
声明不允许直接在类内部进行,那么如何在保持类型定义与类紧密关联的同时实现此行为?是否有推荐的方法将此类类型封装在 TypeScript 的类中?
type
中使用
class
别名是 TypeScript 缺少的功能,请在microsoft/TypeScript#7061 请求。直到并且除非它被实现(虽然它有几百个赞成票,但我没有看到任何迹象表明它会实现),你可以通过声明合并来解决它。 如果您希望
Complex.Input
成为一种类型,则可以有效地将
Complex
用作
namespace
。所以你可以这样声明它,TypeScript 会自动合并它们:
export declare namespace Complex {
export type Input = { real: number, imag: number }
}
export class Complex {
constructor(value: Complex.Input) {
// …
}
}
TypeScript 团队开发负责人在 microsoft/TypeScript#7061中提到此解决方法,称其既不是“非常好”也不是“可怕”。这样做似乎并不常见,但这也不是坏习惯。 我无法真正权威地谈论你是否应该关心像
@typescript-eslint/no-namespace
这样的linter规则,因为它是主观的。 在我看来,反对
namespace
的论点是它是 JavaScipt 模块的较旧替代品。但是
declare namespace Complex
不会创建任何运行时代码;它与类型系统的其余部分一起被完全“擦除”......所以它不一定是违规的。运行时不存在我们鼓励您用 JavaScript 模块替换的“TypeScript 内部模块”。 您可能需要启用 allowDeclarations
选项,以便仅在使用 namespace
生成运行时代码时才标记它们。但同样,这部分是意见,其他人可能会不同意,但没有人“客观”正确。
Playground 代码链接