typescript索引类型_typescript入门:高级类型
學習typescript中 ,有一個小伙伴提出了一個問題
const a = {
a:'1',
b:'2',
c:'3'
}
復制代碼
如何取到每個鍵上的值 ,組成一個聯合類型 ? 即得到一個類型為
type forA = "1" | "2" | "3"
復制代碼
一位大神給出了答案
const a = {
a:'1',
b:'2',
c:'3'
} as const
type t = T[keyof T]
type forA = t //"1" | "2" | "3"
復制代碼
我已經開始迷迷糊糊了。接著提問者又延伸了這個問題
const a = {
a:'1',
b:'2',
c:'3',
d:{
f:'4'
}
}
復制代碼
如何取到每個鍵上的值 (包括一個深層嵌套),組成一個聯合類型 ? 即得到一個類型為
type forA = "1" | "2" | "3" | "4"
復制代碼
過了一會,大神又拿出了回答
const a = {
a:'1',
b:'2',
c:'3',
d:{
f:'4'
}
} as const
type t = {
[K in keyof T]:T extends object
? t
: T[K]
}[keyof T]
type forA = t //"1" | "2" | "3" | "4"
復制代碼
什么?類型里面還有遞歸!對知識查漏補缺,列下以下幾點
定義變量時的 as const
type 內的[K in keyof T]
extends A ? B : C 類型的三目表達式?
類型遞歸?
最后的 [keyof T]
keyof 和 typeof
keyof 獲得接口或者type alias 的鍵
interface interfaceNumber{
one:string,
two:number
}
type typeNumber = {
three:string,
four:number
}
type interfaceKey = keyof interfaceNumber // "one" | "four"
type numberKey = keyof typeNumber // "three" | "four"
復制代碼
typeof使一個上文的某個 Javascript變量 轉換為typescript中的類型
const someType = {
obj:{
one:1
},
arr:[1,2,4],
num:1
}
type t = typeof someType
//{
// obj: {
// one: number;
// };
// arr: number[];
// num: number;
//}
復制代碼
類型系統遞歸地把一個對象上鍵的值轉換為對應類型
as const
把一個數字類型或者字符串類型在轉換為類型時,縮緊為字面量。
const a = 1 as const;
type a1 = typeof a;// 1
const b = "i am b" as const;
type b1 = typeof b;// "i am b"
const c = [1,"23434" , 1] as const
type c1 = typeof noArray // readonly [1, "23434", 1]
復制代碼
如何理解字面量和string類型?字面量也是單獨的一個類型,而類型string ,可以理解為無窮(所有)字面量的聯合 "a" | "b" | "c"|....
它是字面量的全集。同理number
as const 還可以靈活穿插在對象中使用 , 但是數組不行。
const someType = {
obj:{
one:1 as const
},
num:1
}
//typeof someType
//{
// obj: {
// one: 1;
// };
// num: number;
//}
const Array = [1,2 as const , 1]
//typeof Array
//number[]
復制代碼
索引類型 type[key]
索引到interface或者tpye alias 對應鍵的類型
const someType = {
obj:{
one:1
},
arr:[1,2,4],
num:1
}
type t = typeof someType
type obj = t["obj"]//{ one:number }
interface T{
a:string,
t:{
p:number
}
}
type a = T["a"]//string
type p = T["t"]["p"]//number
復制代碼
使用 t.obj 來索引類型是無效的 ,命名空間才可以這么做。
如果索引聯合字符串,則結果也是被索引的鍵的類型的聯合。
interface T{
a:string,
b:number
}
type t1 = T["a" | "b"]// string | number
//或者
type t2 = T[ keyof T ]// string | number
復制代碼
映射類型[ K in keyof T]
只能在type中用。
type getType1= {
[K in keyof T]: T[K]
}
//報錯
//計算屬性名的類型必須為 "string"、"number"、"symbol" 或 "any"。ts(2464)
//成員“[K in keyof”隱式包含類型“any”。ts(7008)
interface getType2{
[K in keyof T]: T[K]
}
復制代碼
可作為固定的語法 [K in keyof T] ,K表示所有 T 中的鍵被拆分成一個個鍵,后面可以聲明類型
const someType = {
obj:{
one:1
},
num:2
}
type getType1= {
[K in keyof T]: T[K]
}
type instance1 = getType1
//{
//obj:{
// one:string
//}
//num:number
//}
復制代碼
keyof T 結果是一組key的聯合,下面原始的語法也是可行的
type Keys = "option1" | "option2";
type Flags = { [K in Keys]: boolean };
復制代碼
你已經發現。映射類型如同JavaScript中的 for(let K in T) 。以下是官方說明
它的語法與索引簽名的語法類型,內部使用了 for .. in。 具有三個部分:
類型變量 K,它會依次綁定到每個屬性。
字符串字面量聯合的 Keys,它包含了要迭代的屬性名的集合。
屬性的結果類型。
我們可以對 T[K] 做一些處理。
const someType = {
obj:{
one:1
},
num:2
}
//extends 類似于三目運算符
type getType1= {
[K in keyof T]: T[K] extends object ? 1 : 0
}
//object類型轉換為字面量1,其他類型為0
type instance1 = getType1//{obj: 1;num: 0;}
復制代碼
extends后面會提及,此處可以簡單作為三目表達式。
泛型函數與遞歸
type或者interface,可以看作一個函數,它可以在{}內部調用自身。
const a {
a:'1',
b:'2',
c:{
d:5
}
} as const
type t = { [ K in typeof T]:T[K] extends object ? t : T[K] }
type forA = t //"1" | "2" | 5
復制代碼
如果沒有泛型參數,它也是泛型函數,也可以調用自身
//這并不報錯
interface Map {
[key: string]: Map;
}
復制代碼
如果沒有{},則不可以調用自身
//Add是把const類型相加的泛型函數
//報錯:類型別名“F”循環引用自身。ts(2456)
type F = T extends 10 ? F> : 0
復制代碼
conditional Type:T extends U ? X : Y
extends 關鍵字
首先說明,typescript多處使用 extends 關鍵字,但它們的作用不盡相同。
//js中的類繼承,與ts無關
class A extends B{}
//接口繼承
interface Shape {
color: string;
}
interface Square extends Shape {
sideLength: number;
}
//泛型約束
//泛型參數T必須有用length鍵且類型為number
type getType1= {
[K in keyof T]: T[K]
}
//約束K必須包括一個或以上T的鍵值
type Pick = {
[P in K]: T[P];
}
//conditional type
type F = T extends object ? 0 : 1
復制代碼
typescript中的extends三種場景,
泛型約束,在你輸入被約束的泛型參數時,強迫輸入值與extends的運算為true
conditional type ,它的運算可真可假 ,true的結果返回X,false返回Y
接口繼承,如果interface A extends B{} , 那么A extends B 是一定為真的
以我的理解,它們含義上是一脈繼承的。
extends運算
上面說extends的含義上有關聯,但是實際conditional type 和 泛型約束在邊緣情況下存在差別。
泛型約束
泛型約束的extends 結果要么是true 要么是 false,這個是明確的,它決定編譯器的報錯與否。
假設 type T ,如A或B有一邊是聯合類型時,它遵循著一個規則,A必須是B子集
具體而言就是,A的每個元素extends B都要為真。
type B = "1" | "2"
type T= {
[key in A] :0
}
T // { "1":0 }
T //{"1":0,"2":0}
T//報錯 不能將類型“"3"”分配給類型“"2" | "1"”。ts(2344)
//相當于
//("1" extends B)&("2" extends B)&("3" extends B)
復制代碼
conditional type
distributive conditional types
conditional types中,如果T是 naked type那么 conditional types就被稱為分配條件類型(distributive conditional types)。
naked type,然而Typescript并沒有說明啥是naked type, 我們大致可以認為就是這個type沒有被包裹在其他的復合結構里,如 array , record , function等。如我們可以通過將T包裹為[T]來破壞naked type
type F = T extends U ? X : Y
type union_type = A | B | C
type a = F
//那么a的結果為 A extends U ? X :Y | B extends U ? X :Y | C extends U ? X : Y
復制代碼
有一點類似泛型約束的分配運算
最后 我們再看看文章開頭的答案
type t = {
[K in keyof T]:T extends object
? t
: T[K]
}[keyof T]
復制代碼
已經可以分析清楚了~
剛剛入門typescript,只是憑借實踐實例得出自己的理解,有誤望指出。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的typescript索引类型_typescript入门:高级类型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java基础 HashMap的添加 修改
- 下一篇: mysql 大表 备份_MySQL大表备