首页 > 解决方案 > ES2015 + flow:自引用(循环?)枚举

问题描述

使用 rollup、buble、flow-remove-types,

是否可以为棋盘表示创建一个 ENUM 类实例,作为类型,如下所示:

// a Ref is a class or a type
class Ref { /* ... */ }

// Refs is an ENUM
Refs.forEach((ref: Ref, key: string) => {
 console.log(key) // outputs: "a1", ..., "h8" successively
}) 

// type checking should work
typeof Refs.a1 === Ref // true
// etc...
typeof Refs.h8 === Ref // true 

// move(ref) --> ref will work
Refs.a1.move(7, 7) === Refs.h8 // true
Refs.h8.move(-7, -7) === Refs.h8 // true

// with...
Refs.a1.move(0, 0) === Refs.a1 // true

// void reference
Refs.a1.move(-1, -1) === null
// or
Refs.a1.move(-1, -1) === Refs.EMPTY

一个可能的模块化实现是将 Ref 类和 Refs 集合打包在同一个文件中,并带有初始化代码,就像 Enuify lib 所做的那样......但是如何使 Ref#move 方法正常工作?

相同:

TicTacToe.X.us =TicTacToe.X
TicTacToe.X.them =TicTacToe.O 
TicTacToe.O.us =TicTacToe.O
TicTacToe.O.them =TicTacToe.X  

标签: javascriptcollectionscircular-dependency

解决方案


像这样的东西,是完美的,但对我来说很好......

type TF = 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'
type TR = '1'|'2'|'3'|'4'|'5'|'6'|'7'|'7'

type TRefDef = {
  file: TF,
  fidx: number,
  rank: TR,
  ridx: number
}

interface IRef {
  move (df: number, dr: number) : IRef
}

const FILES: Array <TF> = 'abcdefgh'.split('')
const RANKS: Array <TR> = '12345678'.split('')

const all: {
  [key:string] : IRef
} = {}

const compute = function(fidx: number, ridx: number): IRef {
  const file: TF = FILES[fidx]
  const rank: TR = RANKS[ridx]

  return all[file + rank]
}

const select = function(key: string) : IRef {
  return all[key]
}

const get = function(arg1: string | number, arg2: ?number) : IRef {
  if(arguments.length ===  1) {
    return select (arg1)
  }

  if(arguments.length ===  2) {
    return compute (arg1, arg2)
  }
}

const each  = function (callback) {
  Object.keys(all).forEach((key, idx) => {
    callback.call(this, all[key], idx)
  })
}

class Ref implements IRef {

  constructor (refdef: TRefDef) {
    this.file = refdef.file
    this.fidx = refdef.fidx
    this.rank = refdef.rank
    this.ridx = refdef.ridx

    this.key = this.file + this.rank
  }

  toString() : string {
    return 'Ref: ' + '(' + this.fidx + ',' + this.ridx + ')' + ' ' + this.file + this.rank
  }

  move (df: number, dr: number) : Ref {
    let f = FILES.indexOf(fidx)
    let r = RANKS.indexOf(ridx)

    f += df
    r += dr

    return all[FILES[f] + RANKS[r]]
  }
}

FILES.forEach((file, fidx) => {
  RANKS.forEach( (rank, ridx) => {
    const key: string = file + rank
    const ref: Ref = new Ref({ file, fidx, rank, ridx })

     all[key] = ref
  })
})


Ref.empty = new Ref('', -1, '', -1)

const Refs = { compute, select, each, get }
// let  f = { compute, each, selection  }
// console.log(f)

// export  { compute, each, select, Ref  }
export  { Refs, Ref  }

推荐阅读