TypeScript JSON для интерфейсов с использованием API компилятора - PullRequest
0 голосов
/ 08 марта 2020

Я пытаюсь динамически генерировать строки локализации, используя API компилятора, я видел этот ответ { ссылка } и хотел использовать его в качестве основы, но мне трудно понять, что сделано, документация также кажется немного минимальным, я написал скрипт в JS, чтобы показать мой требуемый ввод и вывод, ниже ввод:

{
  "hello": {
    "test": ["hello {{name}}", 5],
    "lol": 5,
    "ok": {
      "test": "ok"
    }
  }
}

Ожидаемый вывод:

// Generated by generateLocalizationTypes.js - Do not edit this file directly!

interface HelloTest {
  type: [string | number]
  props: HelloTestProps
}

interface HelloTestProps {
  name: string
}

interface HelloLol {
  type: number
  props: never
}

interface HelloOkTest {
  type: string
  props: never
}
interface LocalizationMap {
  "hello.test": HelloTest
  "hello.lol": HelloLol
  "hello.ok.test": HelloOkTest
}

Что это выглядит как в JS:

const translations = require(`${process.argv[2]}`)
const flatten = require("flat")
const fs = require("fs")

const extractMustacheNotations = val => {
  const allValues = Array.isArray(val) ? val.join("") : val.toString()

  return (allValues.match(/{{\s*[\w\.]+\s*}}/g) || []).map(
    x => x.match(/[\w\.]+/)[0]
  )
}

const seperateAndJoinToPascaleCase = (str, seperator = ".") => {
  return str
    .split(seperator)
    .map(s => s.charAt(0).toUpperCase() + s.slice(1))
    .join("")
}

let header = "interface LocalizationMap {"
let body = ""
let footer = "}"

const createInterfaces = (key, value) => {
  const interfaceName = seperateAndJoinToPascaleCase(key)
  const mustacheNotations = extractMustacheNotations(value)
  body += `  "${key}": ${interfaceName}\n`

  return {
    interface: `
    interface ${interfaceName} {
      type: ${
        Array.isArray(value)
          ? `[${[...new Set(value.map(v => typeof v))].join(" | ")}]`
          : typeof value
      }
      ${
        mustacheNotations.length
          ? `props: ${interfaceName}Props`
          : "props: never"
      }
    }
    `,
    propsInterface: mustacheNotations.length
      ? `
    interface ${interfaceName}Props {
      ${mustacheNotations.map(key => `${key}: string`).join("\n")}
    }
    `
      : undefined,
  }
}

const generateLocalizationTypes = () => {
  const flattenTranslations = flatten(translations, { safe: true })

  const data = `// Generated by generateLocalizationTypes.js - Do not edit this file directly!
${Object.entries(flattenTranslations)
  .map(([key, value]) => {
    const { interface, propsInterface } = createInterfaces(key, value)

    if (propsInterface) {
      return `${interface} ${propsInterface}`
    }

    return `${interface}`
  })
  .join("")
  .concat(header, body, footer)}
`

  fs.writeFile(`${__dirname}/strings.d.ts`, data, err => {
    if (err) {
      return console.log(err)
    }

    console.log("Typings generated successfully")
  })
}

generateLocalizationTypes()

Мне бы очень хотелось посмотреть, как это делается с помощью API компилятора

...