今天要講的東西,讓我超頭痛的,因為TypeScript當中的很多運算符,字面上看起來是一個意思,但實際運作起來又是別的意思,我們今天來看一些運算符跟實際例子吧。
今天準備不足,所以內文大多是官網的範例,再加上自己的詮釋。
看到key
就會覺得是要講物件當中,key-value pair的key,這邊的確是這個意思,這個運算符會提取物件當中那個"key的型別":
interface Person {
name: string;
age: number;
}
// `keyof Person` 會創造出一個Union type: "name" | "age" 這兩個字串
function printPersonProperty(person: Person, property: keyof Person) {
console.log(`${property}: "${person[property]}"`);
}
let person = {
name: "Max",
age: 27
};
printPersonProperty(person, "name"); // name: "Max"
//上面這行第二個參數只能放"name"或者"age"唷,不是任何字串或數字
這樣子的用法我一時不知道要用在哪邊,但後來想想,用在JavaScriptMap
物件上非常好用,畢竟Map
物件key的型別可以不侷限於字串或數字,所以透過keyof
取用一個Map
物件的key,藉此限縮型別,是個不錯的做法。
JavaScript其實已經有typeof這個運算符了,而TypeScript也有一個,但他只能在後面接上一個變數,而不能是一個"值":
let s = "hello";
let n: typeof s;
//typeof後面只能接s"變數",而不能是"值"
乍看之下其實用途不算太大,畢竟我們通常翻得到s
是什麼型別,但作為組合技使用,效果就不錯。
function f() {
return { x: 10, y: 3 };
}
type P = ReturnType<typeof f>;
//所以type P就會是{x: number, y: number}
這個用法可以物件裡面當中,其特地"值"的型別給取出來,有別於上面keyof取的是key的型別,是個有趣的對比:
type Person = { age: number; name: string; alive: boolean };
type Age = Person["age"];
// Age就會代表型別number
在上面例子Person[]的中括號中,我們甚至可以在裡面進行其他運算,達成更複雜的效果:
type Person = { age: number; name: string; alive: boolean };
type I1 = Person["age" | "name"];
//這行我們去取Person物件中,key age"或"key name的型別
//也就是number | string
type I2 = Person[keyof Person];
//這行我們先對Person進行keyof運算,所以得到的結果就是:
// number | string | boolean
type AliveOrName = "alive" | "name";
//我們當然也能用個聯合型別,放進下面中括號內進行運算
type I3 = Person[AliveOrName];
//於是I3指涉的型別就是
//boolean | string
//如果特地想要取用Person當中錯誤的key
type I4 = Person["ali"]
//TypeScript會特地報錯
//Property 'ali' does not exist on type 'Person'.
同樣的,除了物件,我們也能用在陣列上:
const MyArray = [
{ name: "Alice", age: 15 },
{ name: "Bob", age: 23 },
{ name: "Eve", age: 38 },
];
type Person = typeof MyArray[number];
//中括號這邊代表的是數字型別,所以可能是0,1,2,3,4...
//而MyArray[number]只會代表{name: string, age: number}
我們還能再更進一步取用陣列當中的物件當中的值的型別(超饒口吧!)
type Age = typeof MyArray[number]["age"]
講到這邊其實有點昏頭了,像上面中括號內的運算,我們既能像一般物件那樣,去取用特定的key,如["name"]
,卻也能放型別[number]
,但這邊卻不是要拿出number
這個key所代表的value的型別(真的很饒口...)。所以我目前對這些概念只覺得:大概理解就好0rz,真的要用時再來查也不遲。