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

如何解决TypeScript中ESLint的'Type 'T[K]' is not assignable to type 'never''警告?

TypeScript类型错误:Type 'T[K]' is not assignable to type 'never' 解决思路

问题描述

代码功能正常,但以下两行触发ESLint类型警告:

item[key as keyof ICollectionMetaColumn] = value
mapping[key as keyof ISynchronizationTargetMapping] = value

警告内容:

Type 'T[K]' is not assignable to type 'never'.

相关完整代码:

function setValue<T extends ICollectionMetaColumn | ISynchronizationTargetMapping, K extends keyof T>(
  index: number,
  key: K,
  value: T[K],
) {
  if (isICollectionMetaColumn(_metaColumns.value[index])) {
    const item = _metaColumns.value[index] as ICollectionMetaColumn
    // 此处触发警告
    item[key as keyof ICollectionMetaColumn] = value
    emit('update:columns', unref(_metaColumns))
    if (key === 'columnName' && !value && _metaColumns.value.length === 1)
      emit('update:columns', [])
  }
  else {
    const mapping = _metaColumns.value[index] as ISynchronizationTargetMapping
    // 此处触发警告
    mapping[key as keyof ISynchronizationTargetMapping] = value
    emit('update:mapping', unref(_metaColumns))
    if (key === 'destinationField' && !value && _metaColumns.value.length === 1)
      emit('update:mapping', [])
  }
}

function isICollectionMetaColumn(item: ICollectionMetaColumn | ISynchronizationTargetMapping) {
  return !('destinationField' in item)
}


const metaColumns = ref<(ICollectionMetaColumn | ISynchronizationTargetMapping)[]>()

const _metaColumns = ref<(ICollectionMetaColumn | ISynchronizationTargetMapping)[]>(unref(metaColumns).length > 0
  ? unref(metaColumns)
  : Array.isArray(unref(metaColumns)[0]) && isICollectionMetaColumn(unref(metaColumns)[0])
    ? [{ columnName: '', type: 'varchar' }] as ICollectionMetaColumn[]
    : [{ destinationField: '', path: '' }] as ISynchronizationTargetMapping[],
)


interface ICollectionMetaColumn {
  columnName: string
  type: 'bigint' | 'binary' | 'bit' | 'boolean'
}

interface ISynchronizationTargetMapping{
 destinationField: string,
 path: string
}

问题原因

泛型T是ICollectionMetaColumn | ISynchronizationTargetMapping的联合类型,K是T的键,但TypeScript无法将函数分支内的具体类型(比如ICollectionMetaColumn)和泛型参数T关联起来。当你将key断言为某一类型的键时,value的类型T[K]可能属于联合类型中的另一个分支,导致类型不兼容,最终被推导为never。

解决方法

方法1:使用函数重载替代泛型联合

重载可以明确不同参数组合对应的类型,消除类型歧义:

// 定义重载签名
function setValue(index: number, key: keyof ICollectionMetaColumn, value: ICollectionMetaColumn[keyof ICollectionMetaColumn]): void;
function setValue(index: number, key: keyof ISynchronizationTargetMapping, value: ISynchronizationTargetMapping[keyof ISynchronizationTargetMapping]): void;

// 实现函数
function setValue(
  index: number,
  key: keyof ICollectionMetaColumn | keyof ISynchronizationTargetMapping,
  value: any
) {
  const item = _metaColumns.value[index];
  if (isICollectionMetaColumn(item)) {
    item[key as keyof ICollectionMetaColumn] = value as ICollectionMetaColumn[keyof ICollectionMetaColumn];
    emit('update:columns', unref(_metaColumns));
    if (key === 'columnName' && !value && _metaColumns.value.length === 1)
      emit('update:columns', []);
  } else {
    item[key as keyof ISynchronizationTargetMapping] = value as ISynchronizationTargetMapping[keyof ISynchronizationTargetMapping];
    emit('update:mapping', unref(_metaColumns));
    if (key === 'destinationField' && !value && _metaColumns.value.length === 1)
      emit('update:mapping', []);
  }
}

方法2:在分支内明确断言value类型

如果不想改动函数结构,可以在赋值时同时断言value的类型,匹配当前分支的item类型:

// ICollectionMetaColumn分支
const item = _metaColumns.value[index] as ICollectionMetaColumn;
item[key as keyof ICollectionMetaColumn] = value as ICollectionMetaColumn[keyof ICollectionMetaColumn];

// ISynchronizationTargetMapping分支
const mapping = _metaColumns.value[index] as ISynchronizationTargetMapping;
mapping[key as keyof ISynchronizationTargetMapping] = value as ISynchronizationTargetMapping[keyof ISynchronizationTargetMapping];

方法3:优化泛型约束(更严谨的类型关联)

通过泛型约束让TypeScript明确T和分支类型的关联,不过需要调整函数逻辑:

function setValue<T extends ICollectionMetaColumn | ISynchronizationTargetMapping>(
  index: number,
  key: keyof T,
  value: T[keyof T],
) {
  const item = _metaColumns.value[index] as T;
  if ('columnName' in item) {
    (item as ICollectionMetaColumn)[key as keyof ICollectionMetaColumn] = value as ICollectionMetaColumn[keyof ICollectionMetaColumn];
    emit('update:columns', unref(_metaColumns));
    if (key === 'columnName' && !value && _metaColumns.value.length === 1)
      emit('update:columns', []);
  } else {
    (item as ISynchronizationTargetMapping)[key as keyof ISynchronizationTargetMapping] = value as ISynchronizationTargetMapping[keyof ISynchronizationTargetMapping];
    emit('update:mapping', unref(_metaColumns));
    if (key === 'destinationField' && !value && _metaColumns.value.length === 1)
      emit('update:mapping', []);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 05:41:04