diff --git a/src/components/EquativeExplorer.tsx b/src/components/EquativeExplorer.tsx index 563cb75..cefaf36 100644 --- a/src/components/EquativeExplorer.tsx +++ b/src/components/EquativeExplorer.tsx @@ -12,15 +12,13 @@ import { import { equativeMachine, assembleEquativeOutput, - PredicateInput, } from "../lib/equative-machine"; -import words from "../words/words"; +import { nouns, adjectives } from "../words/words"; function uniqueSort(arr: Adjective[]): Adjective[]; function uniqueSort(arr: UnisexNoun[]): UnisexNoun[]; function uniqueSort(arr: (Adjective | UnisexNoun)[]): (Adjective | UnisexNoun)[] { return arr - .filter((v, i, a) => a.findIndex((e) => e.ts === v.ts) === i) .filter((e) => { try { for (let p = 0; p < 12; p++) { @@ -36,13 +34,15 @@ function uniqueSort(arr: (Adjective | UnisexNoun)[]): (Adjective | UnisexNoun)[] .sort((a, b) => a.p.localeCompare(b.p)); } +const unisexNouns = nouns.filter(x => isUnisexNoun(x)) as UnisexNoun[]; + const inputs = { // TODO: instead - have them unique and sorted in the words.ts file - adjectives: uniqueSort(words.adjectives), - unisexNouns: uniqueSort(words.nouns.filter(x => isUnisexNoun(x)) as UnisexNoun[]), + adjectives: uniqueSort(adjectives), + unisexNouns: unisexNouns.sort((a, b) => a.p.localeCompare(b.p)), }; -function makeBlock(e: PredicateInput): T.VerbBlock { +function makeBlock(e: Adjective | UnisexNoun): T.VerbBlock { const makeP = (p: T.Person): T.ArrayOneOrMore => { const b = assembleEquativeOutput(equativeMachine(p, e)); return ("long" in b ? b.long : b) as T.ArrayOneOrMore; @@ -62,7 +62,7 @@ type PredicateType = "adjectives" | "unisexNouns"; // TODO: Plural nouns like shoode const defaultTs = 1527815306; -const defaultPe = inputs.adjectives.find(a => a.ts === defaultTs) || inputs.adjectives[0]; +// const defaultPe = inputs.adjectives.find(a => a.ts === defaultTs) || inputs.adjectives[0]; function EquativeExplorer() { // TODO: Use sticky state @@ -74,7 +74,6 @@ function EquativeExplorer() { function makeOptionLabel(e: T.DictionaryEntry): string { const eng = getEnglishWord(e); - // @ts-ignore - with dumb old typescript const english = typeof eng === "string" ? eng : eng?.singular; return `${e.p} - ${removeFVarients(e.f)} (${english})`; } @@ -91,22 +90,12 @@ function EquativeExplorer() { // setSubjectType(st); // // setPredicate(inputs[pt][0].ts); // } - // @ts-ignore - const pe = (inputs[predicateType].find((a: AdjectiveInput | UnisexNounInput) => ( - a.ts === predicate - ))) as PredicateInput; - const block = (() => { - try { - return makeBlock(pe); - } catch (e) { - console.error("error making equative"); - console.error(e); - setPredicate(defaultTs); - setPredicateType("adjectives"); - return makeBlock(defaultPe); - } - })(); - + const predicatePile = inputs[predicateType] as T.DictionaryEntry[]; + const pe = predicatePile.find(p => p.ts === predicate) as UnisexNoun | Adjective; + if (!pe) return <> + ERROR! + + console.log("predicate in use", pe); return <>
{/*
@@ -183,10 +172,7 @@ function EquativeExplorer() {
- {/* - // @ts-ignore */} - {pe.ts} - + ; } diff --git a/src/lib/equative-machine.test.ts b/src/lib/equative-machine.test.ts index c91aecc..14dcfe8 100644 --- a/src/lib/equative-machine.test.ts +++ b/src/lib/equative-machine.test.ts @@ -3,8 +3,6 @@ import { EquativeMachineOutput, SubjectInput, PredicateInput, - AdjectiveInput, - UnisexNounInput, ParticipleInput, assembleEquativeOutput, } from "./equative-machine"; @@ -57,7 +55,7 @@ const abilities: { { in: { subject: T.Person.FirstSingMale, - predicate: {"ts":1527815306,"i":7530,"p":"ستړی","f":"stúRey","g":"stuRey","e":"tired","c":"adj."} as AdjectiveInput, + predicate: {"ts":1527815306,"i":7530,"p":"ستړی","f":"stúRey","g":"stuRey","e":"tired","c":"adj."} as Adjective, }, out: { subject: [{ p: "زه", f: "zu", e: "I (m.)" }], @@ -68,7 +66,7 @@ const abilities: { { in: { subject: T.Person.SecondPlurFemale, - predicate: {"ts":1527815306,"i":7530,"p":"ستړی","f":"stúRey","g":"stuRey","e":"tired","c":"adj."} as AdjectiveInput, + predicate: {"ts":1527815306,"i":7530,"p":"ستړی","f":"stúRey","g":"stuRey","e":"tired","c":"adj."} as Adjective, }, out: { subject: [{ p: "تاسو", f: "táaso", e: "You (f. pl.)" }, { p: "تاسې", f: "táase", e: "You (f. pl.)"}], @@ -80,7 +78,7 @@ const abilities: { { in: { subject: T.Person.ThirdSingFemale, - predicate: {"ts":1527812798,"i":5595,"p":"خفه","f":"khufa","g":"khufa","e":"sad, upset, angry; choked, suffocated","c":"adj."} as AdjectiveInput, + predicate: {"ts":1527812798,"i":5595,"p":"خفه","f":"khufa","g":"khufa","e":"sad, upset, angry; choked, suffocated","c":"adj."} as Adjective, }, out: { subject: [{ p: "هغه", f: "haghá", e: "She/it (f.)" }], @@ -96,7 +94,7 @@ const abilities: { { in: { subject: T.Person.FirstSingFemale, - predicate: {"ts":1591872915426,"i":696,"p":"افغانی","f":"afghaanéy","g":"afghaaney","e":"Afghan (person)","c":"n. m. unisex"} as UnisexNounInput, + predicate: {"ts":1591872915426,"i":696,"p":"افغانی","f":"afghaanéy","g":"afghaaney","e":"Afghan (person)","c":"n. m. anim. unisex"} as UnisexNoun, }, out: { subject: [{ p: "زه", f: "zu", e: "I (f.)" }], @@ -107,18 +105,32 @@ const abilities: { { in: { subject: T.Person.FirstPlurFemale, - predicate: {"ts":1527814779,"i":935,"p":"انسان","f":"insaan","g":"insaan","e":"human, person","c":"n. m. anim. unisex"} as UnisexNounInput, + predicate: {"ts":1591872915426,"i":696,"p":"افغانی","f":"afghaanéy","g":"afghaaney","e":"Afghan (person)","c":"n. m. anim. unisex"} as UnisexNoun, }, out: { subject: [{ p: "مونږ", f: "moonG", e: "We (f. pl.)" }, { p: "موږ", f: "mooG", e: "We (f. pl.)" }], - predicate: [{ p: "انسانانې", f: "insaanáane", e: "(the) humans" }], + predicate: [ + { p: "افغانیانې", f: "afghaaniyáane", e: "(the) Afghans" }, + { p: "افغانۍ", f: "afghaanúy", e: "(the) Afghans" }, + ], + equative: [{ p: "یو", f: "yoo", e: "are" }], + }, + }, + { + in: { + subject: T.Person.FirstPlurFemale, + predicate: {"ts":1527814779,"i":935,"p":"انسان","f":"insaan","g":"insaan","e":"human, person","c":"n. m. anim. unisex"} as UnisexNoun, + }, + out: { + subject: [{ p: "مونږ", f: "moonG", e: "We (f. pl.)" }, { p: "موږ", f: "mooG", e: "We (f. pl.)" }], + predicate: [{ p: "انسانانې", f: "insaanáane", e: "(the) humans" }, { p: "انسانې", f: "insaane", e: "(the) humans" }], equative: [{ p: "یو", f: "yoo", e: "are" }], }, }, { in: { subject: T.Person.SecondSingFemale, - predicate: {"ts":1527814779,"i":935,"p":"انسان","f":"insaan","g":"insaan","e":"human, person","c":"n. m. anim. unisex"} as UnisexNounInput, + predicate: {"ts":1527814779,"i":935,"p":"انسان","f":"insaan","g":"insaan","e":"human, person","c":"n. m. anim. unisex"} as UnisexNoun, }, out: { subject: [{ p: "ته", f: "tu", e: "You (f.)" }], @@ -137,7 +149,7 @@ const abilities: { entry: { "ts":1527812817,"i":9921,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m." }, plural: false, }, - predicate: {"ts":1527815451,"i":7193,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"} as AdjectiveInput, + predicate: {"ts":1527815451,"i":7193,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"} as Adjective, }, out: { subject: [{ p: "کتاب", f: "kitáab", e: "(A/The) book" }], @@ -151,7 +163,7 @@ const abilities: { entry: { "ts":1527812817,"i":9921,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m." }, plural: true, }, - predicate: {"ts":1527815451,"i":7193,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"} as AdjectiveInput, + predicate: {"ts":1527815451,"i":7193,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"} as Adjective, }, out: { subject: [{ p: "کتابونه", f: "kitaabóona", e: "(The) books" }], @@ -165,7 +177,7 @@ const abilities: { entry: {"ts":1527812797,"i":8542,"p":"ښځه","f":"xúdza","g":"xudza","e":"woman, wife","c":"n. f. anim.","ec":"woman","ep":"women"}, plural: false, }, - predicate: {"ts":1527815451,"i":7193,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"} as AdjectiveInput, + predicate: {"ts":1527815451,"i":7193,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"} as Adjective, }, out: { subject: [{ p: "ښځه", f: "xúdza", e: "(A/The) woman" }], @@ -179,7 +191,7 @@ const abilities: { entry: {"ts":1527812797,"i":8542,"p":"ښځه","f":"xúdza","g":"xudza","e":"woman, wife","c":"n. f. anim.","ec":"woman","ep":"women"}, plural: true, }, - predicate: {"ts":1527815451,"i":7193,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"} as AdjectiveInput, + predicate: {"ts":1527815451,"i":7193,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"} as Adjective, }, out: { subject: [{ p: "ښځې", f: "xúdze", e: "(The) women" }], @@ -194,7 +206,7 @@ const abilities: { entry: {"ts":1527812797,"i":8542,"p":"ښځه","f":"xúdza","g":"xudza","e":"woman, wife","c":"n. f. anim.","ec":"woman","ep":"women"}, plural: true, }, - predicate: {"ts":1527812798,"i":5595,"p":"خفه","f":"khufa","g":"khufa","e":"sad, upset, angry; choked, suffocated","c":"adj."} as AdjectiveInput, + predicate: {"ts":1527812798,"i":5595,"p":"خفه","f":"khufa","g":"khufa","e":"sad, upset, angry; choked, suffocated","c":"adj."} as Adjective, }, out: { subject: [{ p: "ښځې", f: "xúdze", e: "(The) women" }], @@ -210,7 +222,7 @@ const abilities: { { in: { subject: {"ts":1527812790,"i":5747,"p":"خوړل","f":"khoRul","g":"khoRul","e":"to eat, to bite","c":"v. trans.","psp":"خور","psf":"khor","tppp":"خوړ","tppf":"khoR","ec":"eat"} as ParticipleInput, - predicate: {"ts":1527812796,"i":8578,"p":"ښه","f":"xu","g":"xu","e":"good","c":"adj."} as AdjectiveInput, + predicate: {"ts":1527812796,"i":8578,"p":"ښه","f":"xu","g":"xu","e":"good","c":"adj."} as Adjective, }, out: { subject: [{ p: "خوړل", f: "khoRul", e: "eating" }], @@ -221,7 +233,7 @@ const abilities: { { in: { subject: {"ts":1527817298,"i":310,"p":"اخیستل","f":"akheestul","g":"akheestul","e":"to take, buy, purchase, receive; to shave, cut with scissors","c":"v. trans.","psp":"اخل","psf":"akhl","ec":"take,takes,taking,took,taken"} as ParticipleInput, - predicate: {"ts":1527815451,"i":7193,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"} as AdjectiveInput, + predicate: {"ts":1527815451,"i":7193,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"} as Adjective, }, out: { subject: [{ p: "اخیستل", f: "akheestul", e: "taking" }], @@ -232,7 +244,7 @@ const abilities: { { in: { subject: {"ts":1527816854,"i":4365,"p":"جګېدل","f":"jugedul, jigedul","g":"jugedul,jigedul","e":"to get up, be raised up","c":"v. stat. comp. intrans.","l":1527812707,"ec":"get, gets, getting, got, gotten","ep":"up"} as ParticipleInput, - predicate: {"ts":1527815246,"i":7591,"p":"سخت","f":"sakht","g":"sakht","e":"hard, difficult","c":"adj."} as AdjectiveInput, + predicate: {"ts":1527815246,"i":7591,"p":"سخت","f":"sakht","g":"sakht","e":"hard, difficult","c":"adj."} as Adjective, }, out: { subject: [{ p: "جګېدل", f: "jugedul", e: "getting up" }], @@ -367,11 +379,13 @@ const abilities: { plural: true, gender: "fem", }, - predicate: {"ts":1527815451,"i":7193,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"} as AdjectiveInput, + predicate: {"ts":1527815451,"i":7193,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"} as Adjective, }, out: { - // TODO: should also use نرسې ? - subject: [{ p: "نرسانې", f: "narsáane", e: "(The) nurses" }], + subject: [ + { p: "نرسانې", f: "narsáane", e: "(The) nurses" }, + { p: "نرسې", f: "narse", e: "(The) nurses" }, + ], predicate: [{ p: "زړې", f: "zaRe", e: "old" }], equative: [{ p: "دي", f: "dee", e: "are" }], }, @@ -459,4 +473,17 @@ test("assembleEquativeOutput", () => { predicate: [{ p: "زاړه", f: "zaaRu", e: "old" }], equative: [{ p: "دي", f: "dee", e: "are" }], })).toEqual([{ p: "کتابونه زاړه دي", f: "kitaabóona zaaRu dee", e: "(The) books are old" }]); + expect(assembleEquativeOutput({ + subject: [{ p: "مونږ", f: "moonG", e: "We (f. pl.)" }, { p: "موږ", f: "mooG", e: "We (f. pl.)" }], + predicate: [ + { p: "افغانیانې", f: "afghaaniyáane", e: "(the) Afghans" }, + { p: "افغانۍ", f: "afghaanúy", e: "(the) Afghans" }, + ], + equative: [{ p: "یو", f: "yoo", e: "are" }], + })).toEqual([ + { p: "مونږ افغانیانې یو", f: "moonG afghaaniyáane yoo", e: "We (f. pl.) are (the) Afghans" }, + { p: "مونږ افغانۍ یو", f: "moonG afghaanúy yoo", e: "We (f. pl.) are (the) Afghans" }, + { p: "موږ افغانیانې یو", f: "mooG afghaaniyáane yoo", e: "We (f. pl.) are (the) Afghans" }, + { p: "موږ افغانۍ یو", f: "mooG afghaanúy yoo", e: "We (f. pl.) are (the) Afghans" }, + ]); }); \ No newline at end of file diff --git a/src/lib/equative-machine.ts b/src/lib/equative-machine.ts index 00ff305..bd45fdd 100644 --- a/src/lib/equative-machine.ts +++ b/src/lib/equative-machine.ts @@ -13,7 +13,9 @@ import { parseEc, concatPsString, } from "@lingdocs/pashto-inflector"; -import { SingleOrLengthOpts } from "@lingdocs/pashto-inflector/dist/types"; +import { + isArrayOneOrMore, +} from "./type-predicates"; export type EquativeMachineOutput = { subject: T.PsString[], @@ -50,17 +52,26 @@ export function equativeMachine(sub: SubjectInput, pred: PredicateInput): Equati }; } -export function assembleEquativeOutput(o: EquativeMachineOutput): SingleOrLengthOpts { +export function assembleEquativeOutput(o: EquativeMachineOutput): T.SingleOrLengthOpts { if ("long" in o.equative) { return { long: assembleEquativeOutput({ ...o, equative: o.equative.long }) as T.PsString[], short: assembleEquativeOutput({ ...o, equative: o.equative.short }) as T.PsString[], } } - // TODO: make it use all the variations - const ps = concatPsString(o.subject[0], " ", o.predicate[0], " ", o.equative[0]); + // get all possible combinations of subject, predicate, and equative + // soooo cool how this works 🤓 + const equatives = o.equative; + const predicates = o.predicate; + const ps = o.subject.flatMap(subj => ( + predicates.flatMap(pred => ( + equatives.map(eq => ( + concatPsString(subj, " ", pred, " ", eq)) + ) + )) + )); const e = `${o.subject[0].e} ${o.equative[0].e} ${o.predicate[0].e}`; - return [{ ...ps, e }]; + return ps.map(x => ({ ...x, e })); } // LEVEL 2 FUNCTIONS @@ -97,6 +108,7 @@ function makeEntity(e: EntityInput, subjPerson?: T.Person): T.PsString[] { return makeAdjective(e, subjPerson); } if (isUnisexNounInput(e)) { + if (subjPerson === undefined) throw new Error("unspecified unisex noun must be in the predicate"); return makeUnisexNoun(e, subjPerson); } if (isParticipleInput(e)) { @@ -126,41 +138,52 @@ function makePronoun(sub: T.Person): T.PsString[] { ); } -function makeUnisexNoun(e: UnisexNoun, subjPerson: T.Person | undefined): T.PsString[] { +function makeUnisexNoun(e: UnisexNoun, subjPerson: T.Person): T.PsString[] { // reuse english from make noun - do the a / an sensitivity // if it's the predicate - get the inflection according to the subjPerson - if (subjPerson !== undefined) { - const inf = inflectWord(e); - const english = getEnglishFromNoun(e, personIsPlural(subjPerson), "predicate"); - if (!inf) { - return [psStringFromEntry(e, english)]; - } - if (!inf.inflections && (!("plural" in inf) || (!inf.inflections || !isUnisexSet(inf.inflections)))) { - throw Error("improper unisex noun"); - } - // if plural // anim // chose that - // otherwise just chose inflection (or add both) - const pashto = ((): T.ArrayOneOrMore => { - if ("plural" in inf && inf.plural !== undefined && personIsPlural(subjPerson)) { - const gender = personGender(subjPerson); - if (gender === "masc" && "masc" in inf.plural) { - return inf.plural.masc[0]; - } - if (gender === "fem" && "fem" in inf.plural) { - return inf.plural.fem[0]; - } - throw new Error("gender not available for plural"); - } - if (isUnisexSet(inf.inflections)) { - return chooseInflection(inf.inflections, subjPerson); - } else { - return [psStringFromEntry(e, english)]; - } - })(); - return addEnglish(english, pashto); + const inf = inflectWord(e); + const english = getEnglishFromNoun(e, personIsPlural(subjPerson), "predicate"); + const gender = personGender(subjPerson); + if (!inf) { + return [psStringFromEntry(e, english)]; } - // if it's the subject - TO BE IMPLEMENTED - throw new Error("unisex noun as subject not implemented yet"); + // if (!inf.inflections && (!("plural" in inf) || (!inf.inflections || !isUnisexSet(inf.inflections)))) { + // throw Error("improper unisex noun"); + // } + // if plural // anim // chose that + // otherwise just chose inflection (or add both) + const pashto = ((): T.ArrayOneOrMore => { + const plural = personIsPlural(subjPerson); + function getPlural() { + const plural = getInf(inf, "plural", gender, true); + const arabicPlural = getInf(inf, "arabicPlural", gender, true); + const inflections = getInf(inf, "inflections", gender, true) + return [ + ...plural, + ...arabicPlural, + // avoid useless non-inflecting masculine inflection "plural" + ...(plural.length && inflections[0].p === e.p) ? [] : inflections, + ]; + } + const ps = plural + ? getPlural() + : getInf(inf, "inflections", gender, plural); + return isArrayOneOrMore(ps) + ? ps + : [psStringFromEntry(e, english)]; + })(); + return addEnglish(english, pashto); +} + +function getInf(infs: T.InflectorOutput, t: "plural" | "arabicPlural" | "inflections", gender: T.Gender, plural: boolean): T.PsString[] { + // @ts-ignore + if (infs && t in infs && infs[t] !== undefined && gender in infs[t] && infs[t][gender] !== undefined) { + // @ts-ignore + const iset = infs[t][gender] as T.InflectionSet; + const ipick = iset[(t === "inflections" && plural) ? 1 : 0]; + return ipick; + } + return []; } function makeNoun(n: NounInput | SpecifiedUnisexNounInput, entity: "subject" | "predicate"): T.PsString[] { @@ -171,28 +194,16 @@ function makeNoun(n: NounInput | SpecifiedUnisexNounInput, entity: "subject" | " const gender = "gender" in n ? n.gender : n.entry.c?.includes("n. f.") ? "fem" : "masc"; - try { - if (n.plural && infs) { - if ("plural" in infs && infs.plural !== undefined) { - // ts-ignore used here because we know we can trust the gender to work - // @ts-ignore - return infs.plural[gender][0] as T.ArrayOneOrMore; - } - // TODO: Add arabic plural? - if ("inflections" in infs && infs.inflections !== undefined) { - // @ts-ignore - return infs.inflections[gender][1] as T.ArrayOneOrMore; - } - return [psStringFromEntry(n.entry, english)]; - } else if (!n.plural && infs && "inflections" in infs && infs.inflections !== undefined) { - // @ts-ignore - return infs.inflections[gender][0] as T.ArrayOneOrMore; - } - return [psStringFromEntry(n.entry, english)]; - } catch(e) { - console.error(e); - throw new Error("error making noun " + n.entry.ts); - } + const ps = !n.plural + ? getInf(infs, "inflections", gender, false) + : [ + ...getInf(infs, "plural", gender, true), + ...getInf(infs, "arabicPlural", gender, true), + ...getInf(infs, "inflections", gender, true), + ]; + return isArrayOneOrMore(ps) + ? ps + : [psStringFromEntry(n.entry, english)]; })(); return addEnglish(english, pashto); } diff --git a/src/lib/type-predicates.ts b/src/lib/type-predicates.ts index ea173c0..c1a7d8b 100644 --- a/src/lib/type-predicates.ts +++ b/src/lib/type-predicates.ts @@ -2,6 +2,7 @@ import { pashtoConsonants, endsWith, countSyllables, + Types as T, } from "@lingdocs/pashto-inflector"; export function isNoun(e: Word): e is Noun { @@ -132,3 +133,7 @@ export function isPattern6FemNoun(e: FemNoun): e is Pattern6FemNoun { if (e.c.includes("anim.")) return false; return e.p.slice(-1) === "ي"; } + +export function isArrayOneOrMore(a: U[]): a is T.ArrayOneOrMore { + return a.length > 0; +}