最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS實(shí)現(xiàn)JSON轉(zhuǎn)TypeScript接口的核心步驟

 更新時間:2026年02月24日 09:28:10   作者:滕青山  
這篇文章詳細(xì)介紹了如何使用在線工具將JSON數(shù)據(jù)轉(zhuǎn)換為TypeScript接口代碼的全過程,工具通過輸入清洗、JSON解析、類型名生成、類型推斷、對象轉(zhuǎn)聲明文本等步驟,最終生成可讀性強(qiáng)且準(zhǔn)確的TypeScript代碼,需要的朋友可以參考下

這篇只講核心 JS 邏輯:一段 JSON 是如何一步步變成 TypeScript 接口代碼的。

在線工具網(wǎng)址:https://see-tool.com/json-to-typescript
工具截圖:

1)狀態(tài)與入口函數(shù)

先看最核心的狀態(tài)和入口:

const jsonInput = ref('')
const outputData = ref('')
const interfaceName = ref('RootObject')
const useType = ref(false)
const optionalProps = ref(true)
const errorMessage = ref('')

const convert = () => {
  const input = jsonInput.value.trim()
  if (!input) {
    outputData.value = ''
    errorMessage.value = ''
    return
  }

  try {
    const parsed = JSON.parse(input)
    if (parsed === null || (typeof parsed !== 'object' && !Array.isArray(parsed))) {
      errorMessage.value = '根節(jié)點(diǎn)必須是對象或數(shù)組'
      outputData.value = ''
      return
    }
    const rootName = interfaceName.value.trim() || 'RootObject'
    outputData.value = jsonToTypeScript(parsed, rootName)
    errorMessage.value = ''
  } catch (error) {
    errorMessage.value = `JSON 解析失?。?{error.message}`
    outputData.value = ''
  }
}

這里做了三件事:輸入清洗、JSON 解析、調(diào)用生成器。只要這一步跑通,工具就能穩(wěn)定輸出。

2)類型名生成:先合法,再去重

JSON 字段名常常不規(guī)范,比如有空格、短橫線、數(shù)字開頭,所以類型名要先標(biāo)準(zhǔn)化:

const toPascalCase = (value, fallback = 'Item') => {
  const cleaned = String(value || '').replace(/[^A-Za-z0-9_$\s]/g, ' ').trim()
  if (!cleaned) return fallback
  const parts = cleaned.split(/\s+/).filter(Boolean)
  const combined = parts.map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('')
  return /^[A-Za-z_$]/.test(combined) ? combined : fallback
}

const normalizeInterfaceName = (value, fallback = 'RootObject') => {
  if (!value) return fallback
  return toPascalCase(value, fallback) || fallback
}

嵌套對象會不斷生成新接口名,所以還要處理重名:

const interfaceNames = new Set()
const processedNames = new Set()

const generateInterfaceName = (base, suffix = '') => {
  const baseNormalized = normalizeInterfaceName(base, 'RootObject')
  const suffixNormalized = suffix ? toPascalCase(suffix) : ''
  const name = `${baseNormalized}${suffixNormalized}`

  if (!interfaceNames.has(name) && !processedNames.has(name)) {
    interfaceNames.add(name)
    return name
  }

  let counter = 2
  while (interfaceNames.has(`${name}${counter}`) || processedNames.has(`${name}${counter}`)) {
    counter += 1
  }
  const finalName = `${name}${counter}`
  interfaceNames.add(finalName)
  return finalName
}

3)類型推斷:遞歸處理對象和數(shù)組

真正的核心在 inferType

const inferType = (value, key, parentName) => {
  if (value === null) return 'null'

  if (Array.isArray(value)) {
    if (value.length === 0) return 'any[]'
    const elementTypes = new Set(value.map(item => inferType(item, 'Item', parentName)))
    const types = Array.from(elementTypes)
    const inner = types.length === 1 ? types[0] : `(${types.join(' | ')})`
    return `${inner}[]`
  }

  if (typeof value === 'object') {
    const nestedName = generateInterfaceName(parentName, key)
    processObject(value, nestedName)
    return nestedName
  }

  if (typeof value === 'string') return 'string'
  if (typeof value === 'number') return 'number'
  if (typeof value === 'boolean') return 'boolean'
  return 'any'
}

比如 [{ id: 1 }, { id: "2" }] 會得到 (RootItem | RootItem2)[] 或聯(lián)合類型形式,保證類型信息不丟。

4)對象轉(zhuǎn)聲明文本

推斷完類型后,要拼成最終代碼:

const formatPropertyKey = key => {
  const value = String(key)
  const identifier = /^[A-Za-z_$][A-Za-z0-9_$]*$/
  return identifier.test(value) ? value : JSON.stringify(value)
}

const processObject = (obj, name) => {
  if (processedNames.has(name)) return
  processedNames.add(name)

  const optionalMark = optionalProps.value ? '?' : ''
  const lines = []
  lines.push(useType.value ? `export type ${name} = {` : `export interface ${name} {`)

  Object.entries(obj).forEach(([key, value]) => {
    const tsType = inferType(value, key, name)
    const propertyKey = formatPropertyKey(key)
    lines.push(`  ${propertyKey}${optionalMark}: ${tsType};`)
  })

  lines.push('}')
  interfaces.push(lines.join('\n'))
}

如果根節(jié)點(diǎn)本身是數(shù)組,再補(bǔ)一行根類型:

if (Array.isArray(json)) {
  const arrayType = inferType(json, 'Item', baseName)
  const rootLine = `export type ${baseName} = ${arrayType};`
  return interfaces.length ? `${interfaces.join('\n\n')}\n\n${rootLine}` : rootLine
}

5)實(shí)時轉(zhuǎn)換觸發(fā)

輸入實(shí)時更新,但不希望每敲一個字都立即解析,所以用了防抖:

let debounceTimer = null
const scheduleConvert = () => {
  if (debounceTimer) clearTimeout(debounceTimer)
  debounceTimer = setTimeout(() => {
    convert()
  }, 400)
}

watch(jsonInput, scheduleConvert)
watch(interfaceName, scheduleConvert)
watch([useType, optionalProps], convert)

最終效果就是:輸入 JSON、改根接口名、切換 interface/type、切換可選屬性,結(jié)果區(qū)都會自動刷新。

6)完整思路總結(jié)

這套實(shí)現(xiàn)本質(zhì)是三層:

  1. 輸入層:解析 JSON、處理錯誤
  2. 推斷層:遞歸判斷數(shù)據(jù)類型、生成嵌套接口名
  3. 輸出層:拼接 TypeScript 聲明文本

把這三層拆開后,代碼可讀性會很高,讀者也能很容易定位:哪里在“解析”、哪里在“推斷”、哪里在“輸出”。

到此這篇關(guān)于JS實(shí)現(xiàn)JSON轉(zhuǎn)TypeScript接口的核心步驟的文章就介紹到這了,更多相關(guān)JS JSON轉(zhuǎn)TypeScript接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

隆德县| 南京市| 泰宁县| 兴和县| 凤凰县| 商河县| 竹山县| 两当县| 大连市| 驻马店市| 印江| 桐乡市| 白玉县| 府谷县| 江孜县| 平塘县| 桓台县| 山西省| 松阳县| 锦屏县| 石渠县| 囊谦县| 平舆县| 松阳县| 德令哈市| 吉首市| 普陀区| 怀柔区| 文成县| 灵川县| 荆门市| 通江县| 清流县| 繁峙县| 嵊泗县| 搜索| 洪洞县| 新平| 平原县| 德清县| 漳浦县|