const 的妙用

在日常开发中,经常能看到这种 const ROLE = {} as const

原来使用as const 主要是为了在 TypeScript 中将对象 ROLE 的属性设置为只读。从而增强安全性,此外还能帮助 TS 推到更精确的类型。

同时在使用的过程中使用 ROLE[”xxx”] as readonly 可以防止在代码中意外修改 ROLE 的值。

下面是一个权限判断的例子,可以有效的简化代码的逻辑。

export type User = { roles: Role[]; id: string };

type Role = keyof typeof ROLES;
type Permission = (typeof ROLES)[Role][number];

const ROLES = {
  admin: [
    "view:comments",
    "create:comments",
    "update:comments",
    "delete:comments",
  ],
  moderator: ["view:comments", "create:comments", "delete:comments"],
  user: ["view:comments", "create:comments"],
} as const;

export function hasPermission(user: User, permission: Permission) {
  return user.roles.some((role) =>
    (ROLES[role] as readonly Permission[]).includes(permission)
  );
}

// USAGE:
const user: User = { id: "1", roles: ["user"] };

// Can create a comment
hasPermission(user, "create:comments");

// Can view all comments
hasPermission(user, "view:comments");

never类型的妙用

  1. 代码限制
    never 类型限制,例如下面的代码中

    type Method = "GET" | "POST"
    function myFetch(method:Method){
        if(method === "GET"){
        }else if(method === "POST"){
        } // 代码在这里没有什么问题,但是如果Method以后扩展了其他的类型会对逻辑产生问题,而不好察觉。
        else{
          const _n : never = method; // 这里表示不存在,如果扩展了其他类型,这里就会报错,容易排查问题
        }
    }
    
  2. 类型取反
    日常的 typescript开发中你是否遇到这样的需求。对类型取反,例如出了number之外其他的类型都可以。那么可以使用三元表达式来完成。
    x:如果是这个类型?never:使用这个类型,对应的可以封装一下,采用泛型。

    function test<T>(x:T extends number ? never : T ){
    }
    // 可以弄成类型工具
    type BannerType<T,U> = T extends U ? never : T ;