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

如何修复TypeScript联合类型属性不存在错误?能否在useState中用satisfies?

问题描述

我定义了以下TypeScript接口与类型:

interface ICustomImage {
  data: string;
  width: number;
  height: number;
}

type UserImage = string | ICustomImage

interface IUser {
  id: number;
  firstName: string;
  lastName: string;
  image: UserImage
}

通过API获取IUser数据后,我用useState存储:

const [user, setUser] = useState<IUser[]>();

但遇到两个问题:

  1. 自动补全时,无法显示string的方法或ICustomImage的属性;
  2. 明明知道user.image存在width属性,访问user.image.width时却报错:

Property 'width' does not exist on type 'string | ICustomImage'.
Property 'width' does not exist on type 'string'.

想解决:

  • 如何修复类型报错,实现直接访问user.image.data、user.image.width或user.image.height?
  • 能否在useState中使用satisfies关键字?

解决方案

一、修复联合类型访问问题

UserImage是string与ICustomImage的联合类型,TypeScript无法自动推断当前image的具体类型,必须通过类型收窄明确类型:

1. 基础类型守卫

通过判断属性或类型来区分:

// 注意:你当前useState存的是数组,需先取单个用户实例,比如user[0]
const currentUser = user?.[0];
if (currentUser?.image && typeof currentUser.image !== 'string') {
  // 此处TypeScript自动推断image为ICustomImage类型
  console.log(currentUser.image.width);
  console.log(currentUser.image.data);
} else if (typeof currentUser?.image === 'string') {
  // 此处image为string类型,可调用字符串方法
  console.log(currentUser.image.toUpperCase());
}

2. 自定义类型守卫函数

若需要频繁判断,可封装成复用函数:

function isCustomImage(image: UserImage): image is ICustomImage {
  return typeof image !== 'string' && 'width' in image && 'height' in image && 'data' in image;
}

// 使用示例
const currentUser = user?.[0];
if (currentUser && isCustomImage(currentUser.image)) {
  console.log(currentUser.image.width);
}

3. 强制类型断言(谨慎使用)

如果你100%确定当前image是ICustomImage,可以用断言跳过类型检查,但这会绕过TypeScript的校验,数据不符合预期时易出运行时错误:

const currentUser = user?.[0];
console.log((currentUser?.image as ICustomImage).width);

二、useState中使用satisfies关键字

satisfies是TypeScript 4.9+新增的语法,用于验证值是否符合指定类型,但不会改变变量的推断类型。在useState中可以这样用:

// 初始值为空数组时
const [user, setUser] = useState<IUser[]>([] satisfies IUser[]);

// 初始值为undefined时
const [user, setUser] = useState<IUser[] | undefined>(undefined satisfies IUser[] | undefined);

不过它仅用于验证初始值的类型合规性,无法直接解决联合类型的访问问题,核心还是要靠类型收窄处理。

可选优化:统一数据结构

如果API返回的image在业务中不需要同时存在两种类型,可以调整类型定义,用标识字段区分:

interface ICustomImage {
  type: 'custom';
  data: string;
  width: number;
  height: number;
}

interface IStringImage {
  type: 'string';
  url: string;
}

type UserImage = ICustomImage | IStringImage;

此时可以通过type字段更清晰地做类型收窄:

if (currentUser?.image.type === 'custom') {
  console.log(currentUser.image.width);
} else {
  console.log(currentUser.image.url);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 22:01:03