简体   繁体   中英

Re-factor TypeScript code with declaration merging to ES2015 module syntax

I have a class and a namespace with declaration merging defined as follows:

// product.ts

export class Product {
  constructor(public name: string, public seller: Product.Seller, public price: Product.Price) {}
}

export namespace Product {
  export class Seller {
    constructor(public name: string, public country: string) {}
  }

  export class Price {
    constructor(public currency: string, public value: number) {}
  }
}

export default Product

I can import it in another file and use Product, Product.Seller and Product.Price to create new object as well as for type checking:

// index.js

import Product from './product'
    
function discountPrice(price: Product.Price, discount: number): Product.Price {
  return new Product.Price(price.currency, price.value * discount)
}

const seller = new Product.Seller('John', 'US')
const price = new Product.Price('USD', 749.9)
const priceWithDiscount = discountPrice(price, 0.7)
const product = new Product('Dell Laptop', seller, priceWithDiscount)

Everything is working well until I lint the file. I got the error "ES2015 module syntax is preferred over custom TypeScript modules and namespaces."

The error is kind of intuitive and I can easily get rid of it by removing the namespace and import product.ts as a named module:

// product.ts

export class Product {
  constructor(public name: string, public seller: Seller, public price: Price) {}
}

export class Seller {
  constructor(public name: string, public country: string) {}
}

export class Price {
  constructor(public currency: string, public value: number) {}
}

// index.js

import * as Product from './product'

The problem is, now the Product class itself is inside the Product module and I have to refer to it as Product.Product:

const product = new Product.Product('Laptop', seller, priceWithDiscount)

I made another attempt to export default the Product class anonymously, but I still get an error and ended up I have to refer to it as Product.default:

// product.ts

export default class {
  constructor(public name: string, public seller: Seller, public price: Price) {}
}

...

// index.ts

const product = new Product.default('Laptop', seller, priceWithDiscount)

Is it possible to retain the outcome of the original design while adhering to the no-namespace rule? Any help would be greatly appreciated!

With the namespace, the two inner classes essentially became properties of the Product constructor. You can still achieve that with static members:

export class Seller {
  constructor(public name: string, public country: string) { }
}
export class Price {
  constructor(public currency: string, public value: number) { }
}

export class Product {
  constructor(public name: string, public seller: Seller, public price: Price) { }
  static Seller = Seller
  static Price = Price
}

export default Product;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM