格子鸽子 發表於 2024-3-12 18:36:00

TypeScript中的keyof

<p>在 TypeScript 中,&nbsp;<code>keyof</code> 操作符用于获取某种类型的所有键。它返回一个字符串或数字的联合类型,包含对象类型的所有可用键。<code>keyof</code> 主要用于在编译时进行类型检查,以确保你访问的属性是对象实际拥有的键。</p>
<h3>一、基本使用</h3>
<div class="cnblogs_code">
<pre>type Person =<span style="color: rgba(0, 0, 0, 1)"> {
name: string;
age: number;
address: string;
};

type PersonKeys </span>= keyof Person; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 'name' | 'age' | 'address'</span>
<span style="color: rgba(0, 0, 0, 1)">
const key: PersonKeys </span>= "name"; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 合法</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> const invalidKey: PersonKeys = "nonexistent"; // 不合法,会报错</span></pre>
</div>
<p>在 TypeScript 中,<code>typeof</code>&nbsp;与&nbsp;<code>keyof</code>&nbsp;通常一起使用,用于获取对象的属性名(键)的联合类型。这在创建通用函数或操作对象属性时非常有用</p>
<div class="cnblogs_code">
<pre>const person =<span style="color: rgba(0, 0, 0, 1)"> {
    name: </span>"John"<span style="color: rgba(0, 0, 0, 1)">,
    age: </span>30<span style="color: rgba(0, 0, 0, 1)">,
    address: {
      city: </span>"New York"<span style="color: rgba(0, 0, 0, 1)">,
      postalCode: </span>"10001"<span style="color: rgba(0, 0, 0, 1)">,
    },
};

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取键的联合类型</span>
type PersonKeyType = keyof <span style="color: rgba(0, 0, 255, 1)">typeof</span> person; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">PersonKeyType 的类型是 "name" | "age" | "address"</span></pre>
</div>
<p>在上面的例子中,我们先用typeof把对象的所有属性和属性类型都获取到了,这一步是必要的,因为&nbsp;<code class="hyc-common-markdown__code__inline">keyof</code>只能作用于​​类型​​,而不能直接作用于​​值​​,再用keyof把对象属性组成了一个联合类型,它包括了顶层属性&nbsp;<code>"name"</code>&nbsp;和&nbsp;<code>"age"</code>,以及对象“adress”而无法直接获取嵌套对象里面的“city”和“postalCode”。&nbsp;</p>
<p>获取嵌套里面的类型可以逐层提取​</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1. 先获取 address 的类型</span>
type AddressType = <span style="color: rgba(0, 0, 255, 1)">typeof</span> person[<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">address</span><span style="color: rgba(128, 0, 0, 1)">"</span>]; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> { city: string; postalCode: string }

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2. 再用 keyof 提取 address 的键</span>
type AddressKeys = keyof AddressType; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> "city" | "postalCode"</span></pre>
</div>
<h3>二、与泛型结合</h3>
<p>可以将 <code>keyof</code> 与泛型结合使用。‘’<code>K extends keyof T</code>&nbsp;‘’是一种用于泛型约束的语法。它的意思是 <code>K</code> 必须是类型 <code>T</code> 的键(属性名称)之一。这个约束确保了在使用泛型函数或类型时,<code>K</code> 的值只能是 <code>T</code> 类型的属性名称,从而提高类型安全性。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 泛型函数,K 必须是 T 的键之一</span>
<span style="color: rgba(0, 0, 255, 1)">function</span> getProperty&lt;T, K extends keyof T&gt;<span style="color: rgba(0, 0, 0, 1)">(obj: T, key: K): T {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> obj;
}

const person: Person </span>=<span style="color: rgba(0, 0, 0, 1)"> {
name: </span>"John"<span style="color: rgba(0, 0, 0, 1)">,
age: </span>30<span style="color: rgba(0, 0, 0, 1)">,
address: </span>"123 Main St"<span style="color: rgba(0, 0, 0, 1)">
};

const name </span>= getProperty(person, "name"); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 正确,类型为 string</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> const invalid = getProperty(person, "nonexistent"); // 错误,会报错</span></pre>
</div>
<h3>三、限制对象键</h3>
<div class="cnblogs_code">
<pre>const person =<span> {
    name: "John"<span>,
    age: 30<span>,
    address: {
      city: "New York"<span>,
      postalCode: "10001"<span>,
    },
};</span></span></span></span></span></pre>
<pre><br>function getProperty(obj: <span style="color: rgba(0, 0, 255, 1)">typeof</span> person, key: keyof <span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)"> person) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> obj;
}

</span><span style="color: rgba(0, 0, 255, 1)">const</span> personName = getProperty(person, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 类型是 string</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> personAge = getProperty(person, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">age</span><span style="color: rgba(128, 0, 0, 1)">"</span>);   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 类型是 number</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> city = getProperty(person.address, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">city</span><span style="color: rgba(128, 0, 0, 1)">"</span>); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 类型是 string</span></pre>
</div>
<p>这个函数 <code>getProperty</code> 接受一个对象和一个属性名,利用 <code>keyof typeof</code> 来限制属性名的合法性,并返回属性对应的值。</p>
<p><code>keyof</code> 与 <code>typeof</code> 的结合使用提供了更好的类型安全,因为它们反映了对象的实际结构。</p>
<h3>四、与映射类型结合</h3>
<p>可以用 <code>keyof</code> 和映射类型一起使用,创建基于现有类型的新类型。</p>
<div class="cnblogs_code">
<pre>type ReadOnly&lt;T&gt; =<span style="color: rgba(0, 0, 0, 1)"> {
readonly : T;
};

type ReadOnlyPerson </span>= ReadOnly&lt;Person&gt;<span style="color: rgba(0, 0, 0, 1)">;

const readonlyPerson: ReadOnlyPerson </span>=<span style="color: rgba(0, 0, 0, 1)"> {
name: </span>"John"<span style="color: rgba(0, 0, 0, 1)">,
age: </span>30<span style="color: rgba(0, 0, 0, 1)">,
address: </span>"123 Main St"<span style="color: rgba(0, 0, 0, 1)">
};

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> readonlyPerson.age = 31; // 错误,会报错,因为 age 是只读的</span></pre>
</div><br><br>
来源:https://www.cnblogs.com/zimengxiyu/p/18068993
頁: [1]
查看完整版本: TypeScript中的keyof