Skip to content

Commit

Permalink
Do away with enums due to their pitfalls, just use union types or as …
Browse files Browse the repository at this point in the history
…const objects
  • Loading branch information
mwhirls committed Feb 7, 2024
1 parent 2eaa510 commit 7ed827b
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 113 deletions.
10 changes: 9 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,13 @@
"@typescript-eslint"
],
"root": true,
"rules": {}
"rules": {
"no-restricted-syntax": [
"error",
{
"selector": "TSEnumDeclaration",
"message": "Don't declare enums"
}
]
}
}
44 changes: 24 additions & 20 deletions src/internal/details.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
import { IpadicFeatures } from "kuromoji";
import { PartOfSpeech, SymbolType } from "../token.js";

export enum DetailsType {
Suffix = '接尾',
NotIndependent = '非自立',
ConjunctionParticle = '接続助詞',
NaiAdjectiveStem = 'ナイ形容詞語幹',
AdverbialParticle = '副助詞',
ParallelMarker = '並立助詞',
SentenceEndingParticle = '終助詞'
}
type ObjectValues<T> = T[keyof T];

export enum SuffixType {
General = '一般',
SuruConjunction = 'サ変接続', // 現実(化)する
AdjectivalNounStem = '形容動詞語幹', // 現実(的)な
Counter = '助数詞', // 一(本)
AuxillaryVerbStem = '助動詞語幹', // 美味し(そう)
Name = '人名', // 花子(氏)
Area = '地域', // 〇〇(県)
Special = '特殊', // 美し(さ)
Adverbial = '副詞可能', // 三日(後)
}
export const DetailsType = {
Suffix: '接尾',
NotIndependent: '非自立',
ConjunctionParticle: '接続助詞',
NaiAdjectiveStem: 'ナイ形容詞語幹',
AdverbialParticle: '副助詞',
ParallelMarker: '並立助詞',
SentenceEndingParticle: '終助詞'
} as const;
export type DetailsType = ObjectValues<typeof DetailsType>;

export const SuffixType = {
General: '一般',
SuruConjunction: 'サ変接続',
AdjectivalNounStem: '形容動詞語幹',
Counter: '助数詞',
AuxillaryVerbStem: '助動詞語幹',
Name: '人名',
Area: '地域',
Special: '特殊',
Adverbial: '副詞可能',
} as const;
export type SuffixType = ObjectValues<typeof SuffixType>;

export class IpadicPOSDetails {
private readonly token: IpadicFeatures;
Expand Down
10 changes: 5 additions & 5 deletions src/internal/token.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IpadicFeatures } from "kuromoji";
import { ConjugatedForm, ConjugationDetail, DetailType, PartOfSpeech, SymbolDetail, SymbolType, TokenDetail } from "../token.js";
import { ConjugatedForm, ConjugationDetail, PartOfSpeech, SymbolDetail, SymbolType, TokenDetail } from "../token.js";
import { IpadicPOSDetails } from "./details.js";

export class IpadicNode {
Expand Down Expand Up @@ -50,22 +50,22 @@ export class IpadicSymbol extends IpadicNode {
}

export class IpadicSymbolDetail implements SymbolDetail {
type: DetailType.SymbolDetail;
type: "SymbolDetail";
symbolType: SymbolType;

constructor(token: IpadicFeatures) {
this.type = DetailType.SymbolDetail;
this.type = "SymbolDetail";
const details = new IpadicPOSDetails(token);
this.symbolType = details.symbolType() ?? SymbolType.Unknown;
}
}

export class IpadicConjugationDetail implements ConjugationDetail {
type: DetailType.ConjugationDetail;
type: "ConjugationDetail";
conjugatedForm: ConjugatedForm

constructor(conjugatedForm: ConjugatedForm) {
this.type = DetailType.ConjugationDetail;
this.type = "ConjugationDetail";
this.conjugatedForm = conjugatedForm;
}
}
Expand Down
165 changes: 82 additions & 83 deletions src/token.ts
Original file line number Diff line number Diff line change
@@ -1,86 +1,90 @@
// string literals from kuromoji (Mecab IPADIC)
export enum PartOfSpeech {
Filler = 'フィラー',
Interjection = '感動詞',
Symbol = '記号',
iAdjective = '形容詞',
Noun = '名詞',
Verb = '動詞',
Particle = '助詞',
AuxillaryVerb = '助動詞',
Conjunction = '接続詞',
Unknown = '',
}
type ObjectValues<T> = T[keyof T];

// string literals from kuromoji (Mecab IPADIC)
export enum SymbolType {
Alphabet = 'アルファベット',
OpeningBracketParens = '括弧開',
ClosingBracketParens = '括弧閉',
Period = '句点',
Space = '空白',
Comma = '読点',
Unknown = '',
}
// provides strongly typed version of the string literals from kuromoji (Mecab IPADIC)

export const PartOfSpeech = {
Filler: 'フィラー',
Interjection: '感動詞',
Symbol: '記号',
iAdjective: '形容詞',
Noun: '名詞',
Verb: '動詞',
Particle: '助詞',
AuxillaryVerb: '助動詞',
Conjunction: '接続詞',
Unknown: '',
} as const;
export type PartOfSpeech = ObjectValues<typeof PartOfSpeech>;

export const SymbolType = {
Alphabet: 'アルファベット',
OpeningBracketParens: '括弧開',
ClosingBracketParens: '括弧閉',
Period: '句点',
Space: '空白',
Comma: '読点',
Unknown: '',
} as const;
export type SymbolType = ObjectValues<typeof SymbolType>;

// String literals from kuromoji (MeCab IPADIC)
// For examples of how Kuromoji classifies conjugations, see:
// https://qiita.com/ensan_hcl/items/885588c7d2d99de85b44
export enum ConjugatedForm {
ClassicalPlainForm = '文語基本形',
ConditionalForm = '仮定形',
ConditionalContraction1 = '仮定縮約1',
ConditionalContraction2 = '仮定縮約2',
Continuative = '連用形',
ContinuativeConjunction = '連用ニ接続',
EuphonicChangeForm = '音便基本形',
IndeclinableNominalConjunction = '体言接続',
GaruConjunction = 'ガル接続',
GozaiConjunction = '連用ゴザイ接続',
Irrealis = '未然形',
IrrealisNuConjunction = '未然ヌ接続',
IrrealisReruConjunction = '未然レル接続',
IrrealisUConjunction = '未然ウ接続',
ImperativeE = '命令e',
ImperativeI = '命令i',
ImperativeRo = '命令ro',
ImperativeYo = '命令yo',
PlainForm = '基本形',
SpecialIndeclinableNominalConjunction1 = '体言接続特殊',
SpecialIndeclinableNominalConjunction2 = '体言接続特殊2',
SpecialIrrealis = '未然特殊',
TaConjunction = '連用タ接続',
TeConjunction = '連用テ接続',
DeConjunction = '連用デ接続',
}
export const ConjugatedForm = {
ClassicalPlainForm: '文語基本形',
ConditionalForm: '仮定形',
ConditionalContraction1: '仮定縮約1',
ConditionalContraction2: '仮定縮約2',
Continuative: '連用形',
ContinuativeConjunction: '連用ニ接続',
EuphonicChangeForm: '音便基本形',
IndeclinableNominalConjunction: '体言接続',
GaruConjunction: 'ガル接続',
GozaiConjunction: '連用ゴザイ接続',
Irrealis: '未然形',
IrrealisNuConjunction: '未然ヌ接続',
IrrealisReruConjunction: '未然レル接続',
IrrealisUConjunction: '未然ウ接続',
ImperativeE: '命令e',
ImperativeI: '命令i',
ImperativeRo: '命令ro',
ImperativeYo: '命令yo',
PlainForm: '基本形',
SpecialIndeclinableNominalConjunction1: '体言接続特殊',
SpecialIndeclinableNominalConjunction2: '体言接続特殊2',
SpecialIrrealis: '未然特殊',
TaConjunction: '連用タ接続',
TeConjunction: '連用テ接続',
DeConjunction: '連用デ接続',
} as const;
export type ConjugatedForm = ObjectValues<typeof ConjugatedForm>;

// String literals from kuromoji (MeCab IPADIC)
// todo: this list is incomplete
export enum ConjugatedType {
Kuru = 'カ変・来ル',
SuruSpecialClass = 'サ変・−スル',
Zuru = 'サ変・−ズル',
Suru = 'サ変・スル',
Ra = 'ラ変',
Ichidan = '一段',
IchidanKureru = '一段・クレル',
ShimoNidan = '下二段',
KamiNidan = '上二段',
Yodan = '四段',
Godan = '五段',
SpecialMasu = '特殊・マス',
SpecialTa = '特殊・タ',
SpecialYa = '特殊・ヤ',
SpecialDa = '特殊・ダ',
SpecialNai = '特殊・ナイ',
SpecialNu = '特殊・ヌ',
}
export const ConjugatedType = {
Kuru: 'カ変・来ル',
SuruSpecialClass: 'サ変・−スル',
Zuru: 'サ変・−ズル',
Suru: 'サ変・スル',
Ra: 'ラ変',
Ichidan: '一段',
IchidanKureru: '一段・クレル',
ShimoNidan: '下二段',
KamiNidan: '上二段',
Yodan: '四段',
Godan: '五段',
SpecialMasu: '特殊・マス',
SpecialTa: '特殊・タ',
SpecialYa: '特殊・ヤ',
SpecialDa: '特殊・ダ',
SpecialNai: '特殊・ナイ',
SpecialNu: '特殊・ヌ',
} as const;
export type ConjugatedType = ObjectValues<typeof ConjugatedType>;

// String literals from kuromoji (MeCab IPADIC)
export enum WordType {
Known = 'KNOWN',
Unknown = 'UNKNOWN',
}
export const WordType = {
Known: 'KNOWN',
Unknown: 'UNKNOWN',
} as const;
export type WordType = ObjectValues<typeof WordType>;

export interface Token {
pos: PartOfSpeech;
Expand All @@ -92,18 +96,13 @@ export interface Token {
detail?: TokenDetail;
}

export enum DetailType {
SymbolDetail,
ConjugationDetail,
}

export interface SymbolDetail {
type: DetailType.SymbolDetail;
type: 'SymbolDetail';
symbolType: SymbolType;
}

export interface ConjugationDetail {
type: DetailType.ConjugationDetail;
type: 'ConjugationDetail';
conjugatedForm: ConjugatedForm;
}

Expand Down
2 changes: 1 addition & 1 deletion test/adjective.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export function runTestSuite(context: TestContext) {
assert.ok(word.tokens.length >= 1);
const token = word.tokens[0];
assert.ok(token.detail);
assert.equal(token.detail.type, bunsetsu.DetailType.ConjugationDetail);
assert.equal(token.detail.type, "ConjugationDetail");
const detail = token.detail as bunsetsu.ConjugationDetail;
assert.equal(detail.conjugatedForm, conjugatedForm);

Expand Down
2 changes: 1 addition & 1 deletion test/symbol.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function runTestSuite(context: TestContext) {
assert.equal(word.tokens.length, 1);
const token = word.tokens[0];
assert.ok(token.detail);
assert.equal(token.detail.type, bunsetsu.DetailType.SymbolDetail);
assert.equal(token.detail.type, "SymbolDetail");
const detail = token.detail as bunsetsu.SymbolDetail;
assert.equal(detail.symbolType, symbolType);
});
Expand Down
4 changes: 2 additions & 2 deletions test/verb/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function runTest(testCases: VerbTestCase[], conjugatedForm: bunsetsu.Conj
assert.ok(word.tokens.length >= 1);
const token = word.tokens[0];
assert.ok(token.detail);
assert.equal(token.detail!.type, bunsetsu.DetailType.ConjugationDetail);
assert.equal(token.detail!.type, "ConjugationDetail");
const detail = token.detail as bunsetsu.ConjugationDetail;
assert.equal(detail.conjugatedForm, conjugatedForm);

Expand Down Expand Up @@ -64,7 +64,7 @@ export function runTestOnPhrase(testCases: PhraseTestCase[], conjugatedForm: bun
assert.ok(word.tokens.length >= 1);
const token = word.tokens[0];
assert.ok(token.detail);
assert.equal(token.detail!.type, bunsetsu.DetailType.ConjugationDetail);
assert.equal(token.detail!.type, "ConjugationDetail");
const detail = token.detail as bunsetsu.ConjugationDetail;
assert.equal(detail.conjugatedForm, conjugatedForm);

Expand Down

0 comments on commit 7ed827b

Please sign in to comment.