typescript 遇到的一点问题

定义了这样三个接口

export interface Response<T> {
  message: string
  result: Pagenation<T> | T
}

export interface Pagenation<T> {
  page: number
  pageSize: number
  total: number
  items:  T[]
}

export interface AuthEntity {
  accessToken: string
  admin: Admin
  flatMenus: Menu[]
  treeMenus: Menu[]
}

但是在调用的时候发生问题,ts不知道我指向的是谁,怎么判断 我的对象是T还是Pagenation<T>

    const data:Response<AuthEntity> = yield call(getAuth, action.username, action.password)
    let authPath: string[] = []
    // 这里ts 提示找不到flatMenus
    const flatMenus: Menu[] = data.result.flatMenus

clipboard.png

这里应该怎么让ts能够知道我使用的是哪个

阅读 3.3k
4 个回答

关于你这个情况下的类型定义,给你个示例。
下面是代码,也可以直接去 Typescript Playground 看语法检查结果

interface AuthEntity {
    accessToken: string

    // 为了方便模拟数据,简化 AuthEntity 定义
    //   admin: Admin
    //   flatMenus: Menu[]
    //   treeMenus: Menu[]
}

// Pagination 从数组继承,具有数组的完全特性
// 注:Array<T> 和 T[] 都表示 T 数组,但在作为基类时只能用 Array<T> 写法
interface Pagination<T> extends Array<T> {
    page: number,
    pageSize: number,
    total: number
}

// 定义通用混型(混数组和 Pagination)
type MixedCollection<T> = T[] | Pagination<AuthEntity>;

// AuthEntity 的混型集合类型实现
type AuthEntityCollection = MixedCollection<AuthEntity>;

// 模拟产生数据的方法 1,返回普通数组
function result1(): AuthEntityCollection {
    return [
        { accessToken: "1" },
        { accessToken: "4" },
    ];
}

// 模拟产生数据的方法 2,返回 Pagination
function result2(): AuthEntityCollection {
    const data = [
        { accessToken: "1" },
        { accessToken: "4" },
    ] as Pagination<AuthEntity>;

    data.page = 1;
    data.pageSize = 2;
    data.total = 3;

    return data;
}

// 定义类型判定方法,用于判断是否 Pagination,
// 注意返回值类型,它同时为 TypeScript 提供类型推断依据
function isPagination<T>(data: MixedCollection<T>): data is Pagination<T> {
    return ["page", "pageSize", "total"]
        .map(key => typeof (data[key]))
        .every(t => t === "number");
}

// 定义两个消费方法,用于消费不同类型的集合,
// 方便在后面测试(传入参数看会不会报类型错误)
function testWithPagination(data: Pagination<AuthEntity>) { }
function testWithPureArray(data: AuthEntity[]) { }

// 定义对混型数据的处理方法,其中使用 isPagination 来区分类型
function deal(authes: AuthEntityCollection) {
    // 下面注释这句,未进行类型推断之前,会报类型错误
    // testWithPagination(authes);
    // 这句不会出错,因为 Pagination<T> 是 T[] 的子类
    // testWithPureArray(authes)

    if (isPagination(authes)) {
        // TypeScript 此时可认定 authes 是 Pagination<AuthEntity>
        testWithPagination(authes);
    } else {
        // TypeScript 也可以这个分支认定 authes 是 AuthEntity[]
        // 注:本例中即使 Pagination<AuthEntity> 也没问题,因为继承关系
        testWithPureArray(authes);
    }
}

data.result是Pagenation和AuthEntity的联合类型,联合类型只能直接访问两个类型都有的公共属性,而flatMenus只在AuthEntity中存在,在Pagenation不存在,所以不能data.result.flatMenus这样直接访问。

let a=data.result as AuthEntity;
const flatMenus: Menu[] =a.flatMenus;

这样就可以。

问题解决了 是我这里定义的有问题。这种时候不应该用| 而应该直接在接口里用这样的方式来定义

clipboard.png

clipboard.png

好吧,我试着加了 as AuthEntity 好像也不行

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题