keyof 类型操作符

keyof 是TS的类型操作符,用于获取对象类型的所有键名组成的联合类型.

注意: keyof 是获取对象类型的所有键名,不是对象变量的建名. 一定要把变量和类型分清楚.

1 获取一个对象类型的键名

interface ObjectInfo {
 error:string;
 info:string
}
type keys = keyof ObjectInfo; 

// keys: "error"|"info"
"error"|"info" 就是keyof取ObjectInfo对象的健明组成的联合类型.

const k1:keys = "error"; // 正确
const k2:keys = "info";  // 正确
const k2:keys = "success";  // 错误

2 获取数组类型的方法键名

type Arraykeys = keyof Array<any>;
const ak1:arrayKeys = "push"; // 正确
const ak2:arrayKeys = "length";  // 正确
const ak3:arrayKeys = "slice";  // 正确
const ak4:arrayKeys = "some";  // 正确
const ak5:arrayKeys = "abc";  // 错误

3 索引签名
3.1 字符串索引签名: {[key: string]:any }

type IndexSignatureString = {[n: string]: any};
type I = keyof IndexNum; // type I = number|string 为什么n:string的时候 I是的类型是number和string组成的联合类型. TS官方有说明.因为Javascript总是把对象健名转换成字符串. 在JS中obj[0]->obj['0'].我的理解是为了兼容.
const I1:I = 1; // 正确
cosnt I2:I = "1"; // 正确

3.2 数字索引签名: {[n: number]: any}

type IndexSignatureNumber =  {[n: number]: any};
type In = keyof IndexSignatureNumber; // type In = number
const In1:In = 1; // 正确
const In2:In = "1"; // 错误

4 索引签名使用

// 索引签名- 将数组转换成对象
const ArrayIndexToObject = <T,>(arr[T]): {[index: number]: T} =>{ //, 避免与JSX的语法冲突所以加了","
  return arry.reduce((obj, item, index) => {
    obj[item] = item;
    return obj;
  }, {} as {[index:number]: T})
}
console.log(ArrayIndexToObject([11,12,34,55,66]));
//{
//  "0": 11,
//  "1": 12,
//  "2": 34,
//  "3": 55,
//  "4": 66
//}

5 索引签名作为动态属性使用

interface Config {
  darkMode: boolean;
  notification: boolean;
  [key:string]: boolean; //动态属性. 引用Config类型的时候可以写多个.这里的[key:string]:boolean 只是一个占位符.
}

function isDisabled<T extends keyof Config>(config:Config, key: T):Config[T] {
  return config[key];
}

const config:Config = {
  darkMode:true,
  notification: true,
  isEnable: true,  // isEable 动态属性名
  maxLength:true, // maxLength 动态属性名
}

console.log(isDisabled(config, "isEnable")); // true;
console.log(isDisabled(config, "maxLength")); // true;
console.log(isDisabled(config, "isTrue")); // undefined;

6 索引签名的约束性
在上面Config接口中定义了{[key:string]: boolean}字符窜索引签名, 接口中其它属性的值必须是boolean. 比如在Config接口加一个"node"属性其值是"abc"时, TS会报错:Property 'node' of type 'string' is not assignable to 'string' index type 'boolean'. 这个特性在需要有统一类型值的场景非常有用.

TS为什么有这个规定我也想不明白,可能是学的还不够到位,希望网友给出见解.

interface Config {
  node: string; // 错误
  darkMode: boolean;
  notification: boolean;
  [key:string]: boolean; 
}

//如果想要接口Config中的属性只是其它类型可以这样做:
interface Config {
  node: string; // 正确
  darkMode: boolean;
  notification: boolean;
  [key:string]: boolean | string; //....|....或者any,或者更具体的泛型T 
}

7 只读索引签名
在索引签名前面加上readonly 进行修饰. 这样: readonly [key:string]:boolean

interface Config {
  readonly [key:string]:boolean; // 只读索引起签名
  darkMode:boolean;
  notification:boolean;
}

const configIn:Config = {
  darMode:true,
  notification:true,
  isTrue: false
}
configIn['isMaxLength'] = true // 错误不允许添加isMaxLength 属性.

8 模板字面量索引签名

interface Config {
  [key: `chappy${string}]: any;  //表示这个变量key 字符串必须是"chappy....."
}

cosnt Te:Config = {
  chappy123: 123 //ok
} 
posted @ 2025-10-23 16:01  一个行走者  阅读(5)  评论(0)    收藏  举报