You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中如何检测属性是否只读?解决赋值只读属性报错问题

问题解答

是不是不良实践?

这种动态用字符串索引访问DOM元素属性的方式不算绝对的坏实践,但确实存在明显的类型安全风险——DOM元素自带大量只读属性(比如ATTRIBUTE_NODE),直接用任意字符串作为属性名赋值,很容易触发只读属性的赋值错误,同时TypeScript也无法帮你提前规避这类问题。如果只是针对少数明确的可写属性(比如你提到的innerText和src),更稳妥的方式是缩小属性范围,而不是用任意字符串。

解决办法

1. 限定允许的属性列表(推荐)

既然你只需要用到innerText和src,直接把property参数的类型限定为这两个属性的联合类型,TypeScript就能自动校验这些属性的可写性,彻底解决报错:

function fillData(selector: string, property: 'innerText' | 'src', data: string, parentElem: HTMLElement){
  const targetElem = parentElem.querySelector(`[data-${selector}]`)
  if (!targetElem || !property) return

  targetElem[property] = data
}

额外优化:加上targetElem的存在判断,避免null访问风险。

2. 自定义可写属性类型(支持更多属性)

如果需要支持更多DOM元素的可写属性,可以先定义一个过滤掉只读属性和方法的类型,再用这个类型约束property:

// 过滤HTMLElement中可写的非方法属性
type WritableHTMLElementProps = {
  [K in keyof HTMLElement]: 
    // 排除方法类型,排除只读属性
    HTMLElement[K] extends Function ? never : 
    (typeof HTMLElement.prototype[K] extends { writable: false } ? never : K)
}[keyof HTMLElement]

function fillData(selector: string, property: WritableHTMLElementProps, data: string, parentElem: HTMLElement){
  const targetElem = parentElem.querySelector(`[data-${selector}]`)
  if (!targetElem || !property) return

  (targetElem as { [key: string]: string })[property] = data
}

3. 运行时检查属性可写性(支持任意字符串)

如果必须允许传入任意字符串作为属性名,就在运行时用Object.getOwnPropertyDescriptor检查属性是否可写,再执行赋值:

function fillData(selector: string, property: string, data: string, parentElem: HTMLElement){
  const targetElem = parentElem.querySelector(`[data-${selector}]`)
  if (!targetElem || !property) return

  const propDescriptor = Object.getOwnPropertyDescriptor(targetElem, property)
  // 检查属性可写(未标记为只读)
  if (propDescriptor?.writable !== false) {
    (targetElem as Record<string, string>)[property] = data
  }
}

内容的提问来源于stack exchange,提问作者Fexxix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 23:42:29