ES6でクラス名を動的に変更する方法

ES7のdecoratorsでクラスを生成するとクラス名がそのデコレータのものになってしまいます。
例えば:

import React from 'react'

function addAwesomeProperty (Spec, Component = Spec) {
  class AwesomeClass extends React.Component {
    render () {
      return React.createElement(
        Component,
        Object.assign({ awesome: 'yes!' }, this.props)
      )
    }
  }
  return AwesomeClass
}

@addAwesomeProperty
class OriginalClass extends React.Component {
  ...
}

こうすると生成後のクラスの名前は AwesomeClass になってしまいます。これは不便。
だからといってクラス名を以下のように変えようとしても出来ません:

AwesomeClass.name = 'OriginalClass'

なぜなら name プロパティは writable ではないからです:

Object.getOwnPropertyDescriptor(AwesomeClass, 'name')
    { value: 'func',
      writable: false,
      enumerable: false,
      configurable: true }

しかしES6の仕様によると以下の方法で変更できるとの記述を見つけました:

> Object.defineProperty(func, 'name', {value: 'foo', configurable: true});
> func.name
  'foo'

という事は、前述の例を以下のように修正すればクラス名に影響を与えずに済みます:

import React from 'react'

function addAwesomeProperty (Spec, Component = Spec) {
  class AwesomeClass extends React.Component {
    render () {
      return React.createElement(
        Component,
        Object.assign({ awesome: 'yes!' }, this.props)
      )
    }
  }
  // 追加
  Object.defineProperty(AwesomeClass, 'name', { value: Component.name, configurable: true })

  return AwesomeClass
}

まぁ、これが設計として正しいのかは謎です。

蛇足

動的なクラス名を定義する方法として、

const classes = { [ dynamicClassName ]: class { ... } }
classes[dynamicClassName].name  // => dynamicClassName

みたいな方法もあるみたいだけど、自分の環境では常に _class となって上手く行かなかった。
自分のbabelの設定が悪いのかもしれないけど。

投稿者:

Takuya

Digital crafts(man|dog). Love photography. Always making otherwise sleeping. born in 1984.

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中