TypeScript闈㈣瘯棰樻€荤粨
Posted 灏忚秺瓒?,
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TypeScript闈㈣瘯棰樻€荤粨相关的知识,希望对你有一定的参考价值。
绗旇€呮渶杩戣瑁佸憳鍚庝篃鍦ㄦ壘宸ヤ綔锛屽鏋滃ぇ瀹惰寰楁枃绔犱笉閿欙紝甯屾湜鍙互鎻愪緵鍐呮帹鏈轰細
ts鍩虹鐭ヨ瘑澶嶄範
https://juejin.cn/post/684490...
馃槉 ts涓殑璁块棶淇グ绗?/h2>- public锛屼换浣曞湴鏂?/li>
- private锛屽彧鑳藉湪绫荤殑鍐呴儴璁块棶
- protected锛岃兘鍦ㄧ被鐨勫唴閮ㄨ闂拰瀛愮被涓闂?/li>
- readonly锛屽睘鎬ц缃负鍙
馃槉 const鍜宺eadonly鐨勫尯鍒?/h2>- const鐢ㄤ簬鍙橀噺锛宺eadonly鐢ㄤ簬灞炴€?/li>
- const鍦ㄨ繍琛屾椂妫€鏌ワ紝readonly鍦ㄧ紪璇戞椂妫€鏌?/li>
浣跨敤const鍙橀噺淇濆瓨鐨勬暟缁勶紝鍙互浣跨敤push锛宲op绛夋柟娉曘€備絾鏄鏋滀娇鐢?code>ReadonlyArray<number>澹版槑鐨勬暟缁勪笉鑳戒娇鐢╬ush锛宲op绛夋柟娉曘€?/p>
馃槉 鏋氫妇鍜屽父閲忔灇涓撅紙const鏋氫妇锛夌殑鍖哄埆
- 鏋氫妇浼氳缂栬瘧鏃朵細缂栬瘧鎴愪竴涓璞★紝鍙互琚綋浣滃璞′娇鐢?/li>
- const鏋氫妇浼氬湪ts缂栬瘧鏈熼棿琚垹闄わ紝閬垮厤棰濆鐨勬€ц兘寮€閿€
// 鏅€氭灇涓?enum Witcher {
Ciri = \'Queen\',
Geralt = \'Geralt of Rivia\'
}
function getGeraltMessage(arg: {[key: string]: string}): string {
return arg.Geralt
}
getGeraltMessage(Witcher) // Geralt of Rivia
// const鏋氫妇
const enum Witcher {
Ciri = \'Queen\',
Geralt = \'Geralt of Rivia\'
}
const witchers: Witcher[] = [Witcher.Ciri, Witcher.Geralt]
// 缂栬瘧鍚?// const witchers = [\'Queen\', \'Geralt of Rivia\'
馃槉 ts涓璱nterface鍙互缁橣unction/Array/Class鍋氬0鏄庡悧锛?/h2>// 鍑芥暟绫诲瀷
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
let result = source.search(subString);
return result > -1;
}
// Array
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
// Class, constructor瀛樺湪浜庣被鐨勯潤鎬侀儴鍒嗭紝鎵€浠ヤ笉浼氭鏌?interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
ts涓殑this鍜宩s涓殑this鏈変粈涔堝樊寮傦紵
- const鐢ㄤ簬鍙橀噺锛宺eadonly鐢ㄤ簬灞炴€?/li>
- const鍦ㄨ繍琛屾椂妫€鏌ワ紝readonly鍦ㄧ紪璇戞椂妫€鏌?/li>
浣跨敤const鍙橀噺淇濆瓨鐨勬暟缁勶紝鍙互浣跨敤push锛宲op绛夋柟娉曘€備絾鏄鏋滀娇鐢?code>ReadonlyArray<number>澹版槑鐨勬暟缁勪笉鑳戒娇鐢╬ush锛宲op绛夋柟娉曘€?/p>
馃槉 鏋氫妇鍜屽父閲忔灇涓撅紙const鏋氫妇锛夌殑鍖哄埆
- 鏋氫妇浼氳缂栬瘧鏃朵細缂栬瘧鎴愪竴涓璞★紝鍙互琚綋浣滃璞′娇鐢?/li>
- const鏋氫妇浼氬湪ts缂栬瘧鏈熼棿琚垹闄わ紝閬垮厤棰濆鐨勬€ц兘寮€閿€
// 鏅€氭灇涓?enum Witcher {
Ciri = \'Queen\',
Geralt = \'Geralt of Rivia\'
}
function getGeraltMessage(arg: {[key: string]: string}): string {
return arg.Geralt
}
getGeraltMessage(Witcher) // Geralt of Rivia
// const鏋氫妇
const enum Witcher {
Ciri = \'Queen\',
Geralt = \'Geralt of Rivia\'
}
const witchers: Witcher[] = [Witcher.Ciri, Witcher.Geralt]
// 缂栬瘧鍚?// const witchers = [\'Queen\', \'Geralt of Rivia\'
馃槉 ts涓璱nterface鍙互缁橣unction/Array/Class鍋氬0鏄庡悧锛?/h2>// 鍑芥暟绫诲瀷
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
let result = source.search(subString);
return result > -1;
}
// Array
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
// Class, constructor瀛樺湪浜庣被鐨勯潤鎬侀儴鍒嗭紝鎵€浠ヤ笉浼氭鏌?interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
ts涓殑this鍜宩s涓殑this鏈変粈涔堝樊寮傦紵
// 鍑芥暟绫诲瀷
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
let result = source.search(subString);
return result > -1;
}
// Array
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
// Class, constructor瀛樺湪浜庣被鐨勯潤鎬侀儴鍒嗭紝鎵€浠ヤ笉浼氭鏌?interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
涓嶄簡瑙?/p>
馃槉 ts涓浣曟灇涓捐仈鍚堢被鍨嬬殑key?
type Name = { name: string }
type Age = { age: number }
type Union = Name | Age
type UnionKey<P> = P extends infer P ? keyof P : never
type T = UnionKey<Union>
馃槉 ts涓??.銆??銆?.銆乢銆?* 绛夌鍙风殑鍚箟锛?/h2>- ?. 鍙€夐摼
- ?? ?? 绫讳技涓庣煭璺垨锛??閬垮厤浜嗕竴浜涙剰澶栨儏鍐?锛孨aN浠ュ強"",false琚涓篺alse鍊笺€傚彧鏈塽ndefind,null琚涓篺alse鍊笺€?/li>
- !. 鍦ㄥ彉閲忓悕鍚庢坊鍔?锛屽彲浠ユ柇瑷€鎺掗櫎undefined鍜宯ull绫诲瀷
- _ , 澹版槑璇ュ嚱鏁板皢琚紶閫掍竴涓弬鏁帮紝浣嗘偍骞朵笉鍏冲績瀹?/li>
- ** 姹傚箓
- !:锛屽緟浼氬垎閰嶈繖涓彉閲忥紝ts涓嶈鎷呭績
// ??
let x = foo ?? bar();
// 绛変环浜?let x = foo !== null && foo !== undefined ? foo : bar();
// !.
let a: string | null | undefined
a.length // error
a!.length // ok
馃槉 浠€涔堟槸鎶楀彉銆佸弻鍙樸€佸崗鍙樺拰閫嗗彉锛?/h2>- Covariant 鍗忓彉锛孴S瀵硅薄鍏煎鎬ф槸鍗忓彉锛岀埗绫?<= 瀛愮被锛屾槸鍙互鐨勩€傚瓙绫?<= 鐖剁被锛岄敊璇€?/li>
- Contravariant 閫嗗彉锛岀鐢?code>strictFunctionTypes缂栬瘧锛屽嚱鏁板弬鏁扮被鍨嬫槸閫嗗彉鐨勶紝鐖剁被 <= 瀛愮被锛屾槸閿欒銆傚瓙绫?<= 鐖剁被锛屾槸鍙互鐨勩€?/li>
Bivariant 鍙屽悜鍗忓彉锛屽嚱鏁板弬鏁扮殑绫诲瀷榛樿鏄弻鍚戝崗鍙樼殑銆傜埗绫?<= 瀛愮被锛屾槸鍙互鐨勩€傚瓙绫?<= 鐖剁被锛屾槸鍙互鐨勩€?/p>
馃槉 ts涓悓鍚嶇殑interface鎴栬€呭悓鍚嶇殑interface鍜宑lass鍙互鍚堝苟鍚楋紵
- interface浼氬悎骞?/li>
- class涓嶅彲浠ュ悎骞?/li>
馃槉 濡備綍浣縯s椤圭洰寮曞叆骞惰瘑鍒紪璇戜负js鐨刵pm搴撳寘锛?/h2>npm install @types/xxxx
鑷繁娣诲姞鎻忚堪鏂囦欢
馃槉 ts濡備綍鑷姩鐢熸垚搴撳寘鐨勫0鏄庢枃浠讹紵
// ??
let x = foo ?? bar();
// 绛変环浜?let x = foo !== null && foo !== undefined ? foo : bar();
// !.
let a: string | null | undefined
a.length // error
a!.length // ok
- Covariant 鍗忓彉锛孴S瀵硅薄鍏煎鎬ф槸鍗忓彉锛岀埗绫?<= 瀛愮被锛屾槸鍙互鐨勩€傚瓙绫?<= 鐖剁被锛岄敊璇€?/li>
- Contravariant 閫嗗彉锛岀鐢?code>strictFunctionTypes缂栬瘧锛屽嚱鏁板弬鏁扮被鍨嬫槸閫嗗彉鐨勶紝鐖剁被 <= 瀛愮被锛屾槸閿欒銆傚瓙绫?<= 鐖剁被锛屾槸鍙互鐨勩€?/li>
Bivariant 鍙屽悜鍗忓彉锛屽嚱鏁板弬鏁扮殑绫诲瀷榛樿鏄弻鍚戝崗鍙樼殑銆傜埗绫?<= 瀛愮被锛屾槸鍙互鐨勩€傚瓙绫?<= 鐖剁被锛屾槸鍙互鐨勩€?/p>
馃槉 ts涓悓鍚嶇殑interface鎴栬€呭悓鍚嶇殑interface鍜宑lass鍙互鍚堝苟鍚楋紵
- interface浼氬悎骞?/li>
- class涓嶅彲浠ュ悎骞?/li>
馃槉 濡備綍浣縯s椤圭洰寮曞叆骞惰瘑鍒紪璇戜负js鐨刵pm搴撳寘锛?/h2>npm install @types/xxxx
鑷繁娣诲姞鎻忚堪鏂囦欢
馃槉 ts濡備綍鑷姩鐢熸垚搴撳寘鐨勫0鏄庢枃浠讹紵
npm install @types/xxxx
鑷繁娣诲姞鎻忚堪鏂囦欢
馃槉 ts濡備綍鑷姩鐢熸垚搴撳寘鐨勫0鏄庢枃浠讹紵
鍙互閰嶇疆tsconfig.json
鏂囦欢涓殑declaration
鍜?code>outDir
- declaration: true, 灏嗕細鑷姩鐢熸垚澹版槑鏂囦欢
- outDir: \'\', 鎸囧畾鐩綍
馃槉 浠€涔堟槸娉涘瀷
娉涘瀷鐢ㄦ潵鏉ュ垱寤哄彲閲嶇敤鐨勭粍浠讹紝涓€涓粍浠跺彲浠ユ敮鎸佸绉嶇被鍨嬬殑鏁版嵁銆傝繖鏍风敤鎴峰氨鍙互浠ヨ嚜宸辩殑鏁版嵁绫诲瀷鏉ヤ娇鐢ㄧ粍浠躲€?strong>绠€鍗曠殑璇达紝鈥滄硾鍨嬪氨鏄妸绫诲瀷褰撴垚鍙傛暟鈥濄€?/strong>
馃槉 -?锛?readonly 鏄粈涔堝惈涔?/h2>
鐢ㄤ簬鍒犻櫎淇グ绗?/p>
type A = {
a: string;
b: number;
}
type B = {
[K in keyof A]?: A[K]
}
type C = {
[K in keyof B]-?: B[K]
}
type D = {
readonly [K in keyof A]: A[K]
}
type E = {
-readonly [K in keyof A]: A[K]
}
馃槉 TS鏄熀浜庣粨鏋勭被鍨嬪吋瀹?/h2>
typescript鐨勭被鍨嬪吋瀹规槸鍩轰簬缁撴瀯鐨勶紝涓嶆槸鍩轰簬鍚嶄箟鐨勩€備笅闈㈢殑浠g爜鍦╰s涓槸瀹屽叏鍙互鐨勶紝浣嗗湪java绛夊熀浜庡悕涔夌殑璇█鍒欎細鎶涢敊銆?/p>
interface Named { name: string }
class Person {
name: string
}
let p: Named
// ok
p = new Person()
馃槉 const鏂█
const鏂█锛宼ypescript浼氫负鍙橀噺娣诲姞涓€涓嚜韬殑瀛楅潰閲忕被鍨?/p>
- 瀵硅薄瀛楅潰閲忕殑灞炴€э紝鑾峰緱readonly鐨勫睘鎬э紝鎴愪负鍙灞炴€?/li>
- 鏁扮粍瀛楅潰閲忔垚涓簉eadonly tuple鍙鍏冪粍
- 瀛楅潰閲忕被鍨嬩笉鑳借鎵╁睍锛堟瘮濡備粠hello绫诲瀷鍒皊tring绫诲瀷锛?/li>
// type \'"hello"\'
let x = "hello" as const
// type \'readonly [10, 20]\'
let y = [10, 20] as const
// type \'{ readonly text: "hello" }\'
let z = { text: "hello" } as const
馃槉 type 鍜?interface 鐨勫尯鍒?/h2>- 绫诲瀷鍒悕鍙互涓轰换浣曠被鍨嬪紩鍏ュ悕绉般€備緥濡傚熀鏈被鍨嬶紝鑱斿悎绫诲瀷绛?/li>
- 绫诲瀷鍒悕涓嶆敮鎸佺户鎵?/li>
- 绫诲瀷鍒悕涓嶄細鍒涘缓涓€涓湡姝g殑鍚嶅瓧
- 绫诲瀷鍒悕鏃犳硶琚疄鐜?implements)锛岃€屾帴鍙e彲浠ヨ娲剧敓绫诲疄鐜?/li>
- 绫诲瀷鍒悕閲嶅悕鏃剁紪璇戝櫒浼氭姏鍑洪敊璇紝鎺ュ彛閲嶅悕鏃朵細浜х敓鍚堝苟
馃槉 implements 涓?extends 鐨勫尯鍒?/h2>- extends, 瀛愮被浼氱户鎵跨埗绫荤殑鎵€鏈夊睘鎬у拰鏂规硶銆?/li>
implements锛屼娇鐢╥mplements鍏抽敭瀛楃殑绫诲皢闇€瑕佸疄鐜伴渶瑕佸疄鐜扮殑绫荤殑鎵€鏈夊睘鎬у拰鏂规硶銆?/p>
馃槉 鏋氫妇鍜?object 鐨勫尯鍒?/h2>
- 鏋氫妇鍙互閫氳繃鏋氫妇鐨勫悕绉帮紝鑾峰彇鏋氫妇鐨勫€笺€備篃鍙互閫氳繃鏋氫妇鐨勫€艰幏鍙栨灇涓剧殑鍚嶇О銆?/li>
- object鍙兘閫氳繃key鑾峰彇value
- 鏁板瓧鏋氫妇鍦ㄤ笉鎸囧畾鍒濆鍊肩殑鎯呭喌涓嬶紝鏋氫妇鍊间細浠?寮€濮嬮€掑銆?/li>
- 铏界劧鍦ㄨ繍琛屾椂锛屾灇涓炬槸涓€涓湡瀹炲瓨鍦ㄧ殑瀵硅薄銆備絾鏄娇鐢╧eyof鏃剁殑琛屼负鍗村拰鏅€氬璞′笉涓€鑷淬€傚繀椤讳娇鐢╧eyof typeof鎵嶅彲浠ヨ幏鍙栨灇涓炬墍鏈夊睘鎬у悕銆?/li>
馃槉 never, void 鐨勫尯鍒?/h2>- never锛宯ever琛ㄧず姘歌繙涓嶅瓨鍦ㄧ殑绫诲瀷銆傛瘮濡備竴涓嚱鏁版€绘槸鎶涘嚭閿欒锛岃€屾病鏈夎繑鍥炲€笺€傛垨鑰呬竴涓嚱鏁板唴閮ㄦ湁姝诲惊鐜紝姘歌繙涓嶄細鏈夎繑鍥炲€笺€傚嚱鏁扮殑杩斿洖鍊煎氨鏄痭ever绫诲瀷銆?/li>
- void, 娌℃湁鏄剧ず鐨勮繑鍥炲€肩殑鍑芥暟杩斿洖鍊间负void绫诲瀷銆傚鏋滀竴涓彉閲忎负void绫诲瀷锛屽彧鑳借祴浜坲ndefined鎴栬€卬ull銆?/li>
unknown, any鐨勫尯鍒?/h2>
- extends, 瀛愮被浼氱户鎵跨埗绫荤殑鎵€鏈夊睘鎬у拰鏂规硶銆?/li>
implements锛屼娇鐢╥mplements鍏抽敭瀛楃殑绫诲皢闇€瑕佸疄鐜伴渶瑕佸疄鐜扮殑绫荤殑鎵€鏈夊睘鎬у拰鏂规硶銆?/p>
馃槉 鏋氫妇鍜?object 鐨勫尯鍒?/h2>
- 鏋氫妇鍙互閫氳繃鏋氫妇鐨勫悕绉帮紝鑾峰彇鏋氫妇鐨勫€笺€備篃鍙互閫氳繃鏋氫妇鐨勫€艰幏鍙栨灇涓剧殑鍚嶇О銆?/li>
- object鍙兘閫氳繃key鑾峰彇value
- 鏁板瓧鏋氫妇鍦ㄤ笉鎸囧畾鍒濆鍊肩殑鎯呭喌涓嬶紝鏋氫妇鍊间細浠?寮€濮嬮€掑銆?/li>
- 铏界劧鍦ㄨ繍琛屾椂锛屾灇涓炬槸涓€涓湡瀹炲瓨鍦ㄧ殑瀵硅薄銆備絾鏄娇鐢╧eyof鏃剁殑琛屼负鍗村拰鏅€氬璞′笉涓€鑷淬€傚繀椤讳娇鐢╧eyof typeof鎵嶅彲浠ヨ幏鍙栨灇涓炬墍鏈夊睘鎬у悕銆?/li>
馃槉 never, void 鐨勫尯鍒?/h2>- never锛宯ever琛ㄧず姘歌繙涓嶅瓨鍦ㄧ殑绫诲瀷銆傛瘮濡備竴涓嚱鏁版€绘槸鎶涘嚭閿欒锛岃€屾病鏈夎繑鍥炲€笺€傛垨鑰呬竴涓嚱鏁板唴閮ㄦ湁姝诲惊鐜紝姘歌繙涓嶄細鏈夎繑鍥炲€笺€傚嚱鏁扮殑杩斿洖鍊煎氨鏄痭ever绫诲瀷銆?/li>
- void, 娌℃湁鏄剧ず鐨勮繑鍥炲€肩殑鍑芥暟杩斿洖鍊间负void绫诲瀷銆傚鏋滀竴涓彉閲忎负void绫诲瀷锛屽彧鑳借祴浜坲ndefined鎴栬€卬ull銆?/li>
unknown, any鐨勫尯鍒?/h2>
unknown绫诲瀷鍜宎ny绫诲瀷绫讳技銆備笌any绫诲瀷涓嶅悓鐨勬槸銆倁nknown绫诲瀷鍙互鎺ュ彈浠绘剰绫诲瀷璧嬪€硷紝浣嗘槸unknown绫诲瀷璧嬪€肩粰鍏朵粬绫诲瀷鍓嶏紝蹇呴』琚柇瑷€
馃槉 濡備綍鍦?window 鎵╁睍绫诲瀷
declare global {
interface Window {
myCustomFn: () => void;
}
}
澶嶆潅鐨勭被鍨嬫帹瀵奸鐩?/h2>馃 implement UnionToIntersection<T>
type A = UnionToIntersection<{a: string} | {b: string} | {c: string}>
// {a: string} & {b: string} & {c: string}
// 瀹炵幇UnionToIntersection<T>
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
// https://stackoverflow.com/questions/50374908/transform-union-type-to-intersection-type
// https://jkchao.github.io/typescript-book-chinese/tips/infer.html#%E4%B8%80%E4%BA%9B%E7%94%A8%E4%BE%8B
馃槉 implement ToNumber<T>
type A = ToNumber<\'1\'> // 1
type B = ToNumber<\'40\'> // 40
type C = ToNumber<\'0\'> // 0
// 瀹炵幇ToNumber
type ToNumber<T extends string, R extends any[] = []> =
T extends `${R[\'length\']}` ? R[\'length\'] : ToNumber<T, [1, ...R]>;
馃槉 implement Add<A, B>
type A = Add<1, 2> // 3
type B = Add<0, 0> // 0
// 瀹炵幇ADD
type NumberToArray<T, R extends any[]> = T extends R[\'length\'] ? R : NumberToArray<T, [1, ...R]>
type Add<T, R> = [...NumberToArray<T, []>, ...NumberToArray<R, []>][\'length\']
馃槉 implement SmallerThan<A, B>
type A = SmallerThan<0, 1> // true
type B = SmallerThan<1, 0> // false
type C = SmallerThan<10, 9> // false
// 瀹炵幇SmallerThan
type SmallerThan<N extends number, M extends number, L extends any[] = [], R extends any[] = []> =
N extends L[\'length\'] ?
M extends R[\'length\'] ? false : true
:
M extends R[\'length\'] ? false : SmallerThan<N, M, [1, ...L], [1, ...R]>;
馃槉 implement LargerThan<A, B>
type A = LargerThan<0, 1> // false
type B = LargerThan<1, 0> // true
type C = LargerThan<10, 9> // true
// 瀹炵幇LargerThan
type LargerThan<N extends number, M extends number, L extends any[] = [], R extends any[] = []> =
N extends L[\'length\'] ?
false : M extends R[\'length\'] ?
true : LargerThan<N, M, [1, ...L], [1, ...R]>;
馃槉 implement IsAny<T>
type A = IsAny<string> // false
type B = IsAny<any> // true
type C = IsAny<unknown> // false
type D = IsAny<never> // false
// 瀹炵幇IsAny
type IsAny<T> = true extends (T extends never ? true : false) ?
false extends (T extends never ? true : false) ?
true
:
false
:
false;
// 鏇寸畝鍗曠殑瀹炵幇
type IsAny<T> = 0 extends (T & 1) ? true : false;
馃槉 implement Filter<T, A>
type A = Filter<[1,\'BFE\', 2, true, \'dev\'], number> // [1, 2]
type B = Filter<[1,\'BFE\', 2, true, \'dev\'], string> // [\'BFE\', \'dev\']
type C = Filter<[1,\'BFE\', 2, any, \'dev\'], string> // [\'BFE\', any, \'dev\']
// 瀹炵幇Filter
type Filter<T extends any[], A, N extends any[] = []> =
T extends [infer P, ...infer Q] ?
0 extends (P & 1) ? Filter<Q, A, [...N, P]> :
P extends A ? Filter<Q, A, [...N, P]> : Filter<Q, A, N>
: N;
馃槉 implement TupleToString<T>
type A = TupleToString<[\'a\']> // \'a\'
type B = TupleToString<[\'B\', \'F\', \'E\']> // \'BFE\'
type C = TupleToString<[]> // \'\'
// 瀹炵幇TupleToString
type TupleToString<T extends any[], S extends string = \'\', A extends any[] = []> =
A[\'length\'] extends T[\'length\'] ? S : TupleToString<T, `${S}${T[A[\'length\']]}`, [1, ...A]>
馃槉 implement RepeatString<T, C>
type A = RepeatString<\'a\', 3> // \'aaa\'
type B = RepeatString<\'a\', 0> // \'\'
// 瀹炵幇RepeatString
type RepeatString<T extends string, C extends number, S extends string = \'\', A extends any[] = []> =
A[\'length\'] extends C ? S : RepeatString<T, C, `${T}${S}`, [1, ...A]>
馃槉 implement Push<T, I>
type A = Push<[1,2,3], 4> // [1,2,3,4]
type B = Push<[1], 2> // [1, 2]
type C = Push<[], string> // [string]
// 瀹炵幇Push
type Push<T extends any[], I> = T extends [...infer P] ? [...P, I] : [I]
馃槉 implement Flat<T>
type A = Flat<[1,2,3]> // [1,2,3]
type B = Flat<[1,[2,3], [4,[5,[6]]]]> // [1,2,3,4,5,6]
type C = Flat<[]> // []
// 瀹炵幇Flat
type Flat<T extends any[]> =
T extends [infer P, ...infer Q] ?
P extends any[] ? [...Flat<P>, ...Flat<Q>] : [P, ...Flat<Q>]
: [];
馃槉 implement Shift<T>
type A = Shift<[1,2,3]> // [2,3]
type B = Shift<[1]> // []
type C = Shift<[]> // []
// 瀹炵幇Shift
type Shift<T extends any[]> = T extends [infer P, ...infer Q] ? [...Q] : [];
馃槉 implement Repeat<T, C>
type A = Repeat<number, 3> // [number, number, number]
type B = Repeat<string, 2> // [string, string]
type C = Repeat<1, 1> // [1, 1]
type D = Repeat<0, 0> // []
// 瀹炵幇Repeat
type Repeat<T, C, R extends any[] = []> =
R[\'length\'] extends C ? R : Repeat<T, C, [...R, T]>
馃槉 implement ReverseTuple<T>
type A = ReverseTuple<[string, number, boolean]> // [boolean, number, string]
type B = ReverseTuple<[1,2,3]> // [3,2,1]
type C = ReverseTuple<[]> // []
// 瀹炵幇ReverseTuple
type ReverseTuple<T extends any[], A extends any[] = []> =
T extends [...infer Q, infer P] ?
A[\'length\'] extends T[\'length\'] ? A : ReverseTuple<Q, [...A, P]>
: A;
馃槉 implement UnwrapPromise<T>
type A = UnwrapPromise<Promise<string>> // string
type B = UnwrapPromise<Promise<null>> // null
type C = UnwrapPromise<null> // Error
// 瀹炵幇UnwrapPromise
type UnwrapPromise<T> = T extends Promise<infer P> ? P : Error;
馃槉 implement LengthOfString<T>
type A = LengthOfString<\'BFE.dev\'> // 7
type B = LengthOfString<\'\'> // 0
// 瀹炵幇LengthOfString
type LengthOfString<T extends string, A extends any[] = []> =
T extends `${infer P}${infer Q}` ? LengthOfString<Q, [1, ...A]> : A[\'length\']
馃槉 implement StringToTuple<T>
type A = StringToTuple<\'BFE.dev\'> // [\'B\', \'F\', \'E\', \'.\', \'d\', \'e\',\'v\']
type B = StringToTuple<\'\'> // []
// 瀹炵幇
type StringToTuple<T extends string, A extends any[] = []> =
T extends `${infer K}${infer P}` ? StringToTuple<P, [...A, K]> : A;
馃槉 implement LengthOfTuple<T>
type A = LengthOfTuple<[\'B\', \'F\', \'E\']> // 3
type B = LengthOfTuple<[]> // 0
// 瀹炵幇
type LengthOfTuple<T extends any[], R extends any[] = []> =
R[\'length\'] extends T[\'length\'] ? R[\'length\'] : LengthOfTuple<T, [...R, 1]>
馃槉 implement LastItem<T>
type A = LastItem<[string, number, boolean]> // boolean
type B = LastItem<[\'B\', \'F\', \'E\']> // \'E\'
type C = LastItem<[]> // never
// 瀹炵幇LastItem
type LastItem<T> = T extends [...infer P, infer Q] ? Q : never;
馃槉 implement FirstItem<T>
type A = FirstItem<[string, number, boolean]> // string
type B = FirstItem<[\'B\', \'F\', \'E\']> // \'B\'
// 瀹炵幇FirstItem
type FirstItem<T> = T extends [infer P, ...infer Q] ? P : never;
馃槉 implement FirstChar<T>
type A = FirstChar<\'BFE\'> // \'B\'
type B = FirstChar<\'dev\'> // \'d\'
type C = FirstChar<\'\'> // never
// 瀹炵幇FirstChar
type FirstChar<T> = T extends `${infer P}${infer Q}` ? P : never;
馃槉 implement Pick<T, K>
type Foo = {
a: string
b: number
c: boolean
}
type A = MyPick<Foo, \'a\' | \'b\'> // {a: string, b: number}
type B = MyPick<Foo, \'c\'> // {c: boolean}
type C = MyPick<Foo, \'d\'> // Error
// 瀹炵幇MyPick<T, K>
type MyPick<T, K extends keyof T> = {
[Key in K]: T[Key]
}
馃槉 implement Readonly<T>
type Foo = {
a: string
}
const a:Foo = {
a: \'BFE.dev\',
}
a.a = \'bigfrontend.dev\'
// OK
const b:MyReadonly<Foo> = {
a: \'BFE.dev\'
}
b.a = \'bigfrontend.dev\'
// Error
// 瀹炵幇MyReadonly
type MyReadonly<T> = {
readonly [K in keyof T]: T[K]
}
馃槉 implement Record<K, V>
type Key = \'a\' | \'b\' | \'c\'
const a: Record<Key, string> = {
a: \'BFE.dev\',
b: \'BFE.dev\',
c: \'BFE.dev\'
}
a.a = \'bigfrontend.dev\' // OK
a.b = 123 // Error
a.d = \'BFE.dev\' // Error
type Foo = MyRecord<{a: string}, string> // Error
// 瀹炵幇MyRecord
type MyRecord<K extends number | string | symbol, V> = {
[Key in K]: V
}
馃锔?implement Exclude
type Foo = \'a\' | \'b\' | \'c\'
type A = MyExclude<Foo, \'a\'> // \'b\' | \'c\'
type B = MyExclude<Foo, \'c\'> // \'a\' | \'b
type C = MyExclude<Foo, \'c\' | \'d\'> // \'a\' | \'b\'
type D = MyExclude<Foo, \'a\' | \'b\' | \'c\'> // never
// 瀹炵幇 MyExclude<T, K>
type MyExclude<T, K> = T extends K ? never : T;
馃锔?implement Extract<T, U>
type Foo = \'a\' | \'b\' | \'c\'
type A = MyExtract<Foo, \'a\'> // \'a\'
type B = MyExtract<Foo, \'a\' | \'b\'> // \'a\' | \'b\'
type C = MyExtract<Foo, \'b\' | \'c\' | \'d\' | \'e\'> // \'b\' | \'c\'
type D = MyExtract<Foo, never> // never
// 瀹炵幇MyExtract<T, U>
type MyExtract<T, U> = T extends U ? T : never
馃槉 implement Omit<T, K>
type Foo = {
a: string
b: number
c: boolean
}
type A = MyOmit<Foo, \'a\' | \'b\'> // {c: boolean}
type B = MyOmit<Foo, \'c\'> // {a: string, b: number}
type C = MyOmit<Foo, \'c\' | \'d\'> // {a: string, b: number}
// 瀹炵幇MyOmit
type MyOmit<T, K extends number | string | symbol> = {
[Key in Exclude<keyof T, K>]: T[Key]
}
type MyOmit<T, K extends number | string | symbol> = Pick<T, Exclude<keyof T, K>>
馃槉 implement NonNullable<T>
type Foo = \'a\' | \'b\' | null | undefined
type A = MyNonNullable<Foo> // \'a\' | \'b\'
// 瀹炵幇NonNullable
type MyNonNullable<T> = T extends null | undefined ? never : T;
馃槉 implement Parameters<T>
type Foo = (a: string, b: number, c: boolean) => string
type A = MyParameters<Foo> // [a:string, b: number, c:boolean]
type B = A[0] // string
type C = MyParameters<{a: string}> // Error
// 瀹炵幇MyParameters<T>
type MyParameters<T extends (...params: any[]) => any> =
T extends (...params: [...infer P]) => any ? P : never
馃槉 implement ConstructorParameters<T>
class Foo {
constructor (a: string, b: number, c: boolean) {}
}
type C = MyConstructorParameters<typeof Foo>
// [a: string, b: number, c: boolean]
// 瀹炵幇MyConstructorParameters<T>
type MyConstructorParameters<T extends new (...params: any[]) => any> =
T extends new (...params: [...infer P]) => any ? P : never
馃槉 implement ReturnType<T>
type Foo = () => {a: string}
type A = MyReturnType<Foo> // {a: string}
// 瀹炵幇MyReturnType<T>
type MyReturnType<T extends (...params: any[]) => any> =
T extends (...params: any[]) => infer P ? P : never;
馃槉 implement InstanceType<T>
class Foo {}
type A = MyInstanceType<typeof Foo> // Foo
type B = MyInstanceType<() => string> // Error
// 瀹炵幇MyInstanceType<T>
type MyInstanceType<T extends new (...params: any[]) => any> =
T extends new (...params: any[]) => infer P ? P : never;
馃槉 implement ThisParameterType<T>
function Foo(this: {a: string}) {}
function Bar() {}
type A = MyThisParameterType<typeof Foo> // {a: string}
type B = MyThisParameterType<typeof Bar> // unknown
// 瀹炵幇MyThisParameterType<T>
type MyThisParameterType<T extends (this: any, ...params: any[]) => any> =
T extends (this: infer P, ...params: any[]) => any ? P : unknown;
馃槉 implement TupleToUnion<T>
type Foo = [string, number, boolean]
type Bar = TupleToUnion<Foo> // string | number | boolean
// 瀹炵幇TupleToUnion<T>
type TupleToUnion<T extends any[], R = T[0]> =
T extends [infer P, ...infer Q] ? TupleToUnion<Q, R | P> : R;
// 鍏朵粬鍥炵瓟
type TupleToUnion<T extends any[]> = T[number]
馃槉 implement Partial<T>
type Foo = {
a: string
b: number
c: boolean
}
// below are all valid
const a: MyPartial<Foo> = {}
const b: MyPartial<Foo> = {
a: \'BFE.dev\'
}
const c: MyPartial<Foo> = {
b: 123
}
const d: MyPartial<Foo> = {
b: 123,
c: true
}
const e: MyPartial<Foo> = {
a: \'BFE.dev\',
b: 123,
c: true
}
// 瀹炵幇MyPartial<T>
type MyPartial<T> = {
[K in keyof T]?: T[K]
}
馃槉 Required<T>
// all properties are optional
type Foo = {
a?: string
b?: number
c?: boolean
}
const a: MyRequired<Foo> = {}
// Error
const b: MyRequired<Foo> = {
a: \'BFE.dev\'
}
// Error
const c: MyRequired<Foo> = {
b: 123
}
// Error
const d: MyRequired<Foo> = {
b: 123,
c: true
}
// Error
const e: MyRequired<Foo> = {
a: \'BFE.dev\',
b: 123,
c: true
}
// valid
// 瀹炵幇MyRequired<T>
type MyRequired<T> = {
[K in keyof T]-?: T[K]
}
馃槉 implement LastChar<T>
type A = LastChar<\'BFE\'> // \'E\'
type B = LastChar<\'dev\'> // \'v\'
type C = LastChar<\'\'> // never
// 瀹炵幇FirstChar<T>
type LastChar<T extends string, A extends string[] = []> =
T extends `${infer P}${infer Q}` ? LastChar<Q, [...A, P]> :
A extends [...infer L, infer R] ? R : never
;
馃槉 implement IsNever<T>
// https://stackoverflow.com/questions/53984650/typescript-never-type-inconsistently-matched-in-conditional-type
// https://www.typescriptlang.org/docs/handbook/advanced-types.html#v
type A = IsNever<never> // true
type B = IsNever<string> // false
type C = IsNever<undefined> // false
// 瀹炵幇IsNever<T>
type IsNever<T> = [T] extends [never] ? true : false;
馃槉 implement KeysToUnion<T>
type A = KeyToUnion<{
a: string;
b: number;
c: symbol;
}>
// \'a\' | \'b\' | \'c\'
// 瀹炵幇KeyToUnion
type KeyToUnion<T> = {
[K in keyof T]: K;
}[keyof T]
馃槉 implement ValuesToUnion<T>
type A = ValuesToUnion<{
a: string;
b: number;
c: symbol;
}>
// string | number | symbol
// ValuesToUnion
type ValuesToUnion<T> = T[keyof T]
FindIndex<T, E>
https://bigfrontend.dev/zh/ty...
type IsAny<T> = 0 extends (T & 1) ? true : false;
type IsNever<T> = [T] extends [never] ? true : false;
type TwoAny<A, B> = IsAny<A> extends IsAny<B> ? IsAny<A> : false;
type TwoNever<A, B> = IsNever<A> extends IsNever<B> ? IsNever<A> : false;
type SingleAny<A, B> = IsAny<A> extends true ? true : IsAny<B>
type SingleNever<A, B> = IsNever<A> extends true ? true : IsNever<B>
type FindIndex<T extends any[], E, A extends any[] = []> =
T extends [infer P, ...infer Q] ?
TwoAny<P, E> extends true ?
A[\'length\']
:
TwoNever<P, E> extends true ?
A[\'length\']
:
SingleAny<P, E> extends true ?
FindIndex<Q, E, [1, ...A]>
:
SingleNever<P, E> extends true ?
FindIndex<Q, E, [1, ...A]>
:
P extends E ? A[\'length\'] : FindIndex<Q, E, [1, ...A]>
:
never
implement Trim<T>
type A = Trim<\' BFE.dev\'> // \'BFE\'
type B = Trim<\' BFE. dev \'> // \'BFE. dev\'
type C = Trim<\' BFE . dev \'> // \'BFE . dev\'
type StringToTuple<T extends string, A extends any[] = []> =
T extends `${infer K}${infer P}` ? StringToTuple<P, [...A, K]> : A;
type TupleToString<T extends any[], S extends string = \'\', A extends any[] = []> =
A[\'length\'] extends T[\'length\'] ? S : TupleToString<T, `${S}${T[A[\'length\']]}`, [1, ...A]>
type Trim<T extends string, A extends any[] = StringToTuple<T>> =
A extends [infer P, ...infer Q] ?
P extends \' \' ?
Trim<T, Q>
:
A extends [...infer M, infer N] ?
N extends \' \' ?
Trim<T, M>
:
TupleToString<A>
:
\'\'
:
\'\';
type A = UnionToIntersection<{a: string} | {b: string} | {c: string}>
// {a: string} & {b: string} & {c: string}
// 瀹炵幇UnionToIntersection<T>
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
// https://stackoverflow.com/questions/50374908/transform-union-type-to-intersection-type
// https://jkchao.github.io/typescript-book-chinese/tips/infer.html#%E4%B8%80%E4%BA%9B%E7%94%A8%E4%BE%8B
type A = ToNumber<\'1\'> // 1
type B = ToNumber<\'40\'> // 40
type C = ToNumber<\'0\'> // 0
// 瀹炵幇ToNumber
type ToNumber<T extends string, R extends any[] = []> =
T extends `${R[\'length\']}` ? R[\'length\'] : ToNumber<T, [1, ...R]>;
type A = Add<1, 2> // 3
type B = Add<0, 0> // 0
// 瀹炵幇ADD
type NumberToArray<T, R extends any[]> = T extends R[\'length\'] ? R : NumberToArray<T, [1, ...R]>
type Add<T, R> = [...NumberToArray<T, []>, ...NumberToArray<R, []>][\'length\']
type A = SmallerThan<0, 1> // true
type B = SmallerThan<1, 0> // false
type C = SmallerThan<10, 9> // false
// 瀹炵幇SmallerThan
type SmallerThan<N extends number, M extends number, L extends any[] = [], R extends any[] = []> =
N extends L[\'length\'] ?
M extends R[\'length\'] ? false : true
:
M extends R[\'length\'] ? false : SmallerThan<N, M, [1, ...L], [1, ...R]>;
type A = LargerThan<0, 1> // false
type B = LargerThan<1, 0> // true
type C = LargerThan<10, 9> // true
// 瀹炵幇LargerThan
type LargerThan<N extends number, M extends number, L extends any[] = [], R extends any[] = []> =
N extends L[\'length\'] ?
false : M extends R[\'length\'] ?
true : LargerThan<N, M, [1, ...L], [1, ...R]>;
type A = IsAny<string> // false
type B = IsAny<any> // true
type C = IsAny<unknown> // false
type D = IsAny<never> // false
// 瀹炵幇IsAny
type IsAny<T> = true extends (T extends never ? true : false) ?
false extends (T extends never ? true : false) ?
true
:
false
:
false;
// 鏇寸畝鍗曠殑瀹炵幇
type IsAny<T> = 0 extends (T & 1) ? true : false;
type A = Filter<[1,\'BFE\', 2, true, \'dev\'], number> // [1, 2]
type B = Filter<[1,\'BFE\', 2, true, \'dev\'], string> // [\'BFE\', \'dev\']
type C = Filter<[1,\'BFE\', 2, any, \'dev\'], string> // [\'BFE\', any, \'dev\']
// 瀹炵幇Filter
type Filter<T extends any[], A, N extends any[] = []> =
T extends [infer P, ...infer Q] ?
0 extends (P & 1) ? Filter<Q, A, [...N, P]> :
P extends A ? Filter<Q, A, [...N, P]> : Filter<Q, A, N>
: N;
type A = TupleToString<[\'a\']> // \'a\'
type B = TupleToString<[\'B\', \'F\', \'E\']> // \'BFE\'
type C = TupleToString<[]> // \'\'
// 瀹炵幇TupleToString
type TupleToString<T extends any[], S extends string = \'\', A extends any[] = []> =
A[\'length\'] extends T[\'length\'] ? S : TupleToString<T, `${S}${T[A[\'length\']]}`, [1, ...A]>
type A = RepeatString<\'a\', 3> // \'aaa\'
type B = RepeatString<\'a\', 0> // \'\'
// 瀹炵幇RepeatString
type RepeatString<T extends string, C extends number, S extends string = \'\', A extends any[] = []> =
A[\'length\'] extends C ? S : RepeatString<T, C, `${T}${S}`, [1, ...A]>
type A = Push<[1,2,3], 4> // [1,2,3,4]
type B = Push<[1], 2> // [1, 2]
type C = Push<[], string> // [string]
// 瀹炵幇Push
type Push<T extends any[], I> = T extends [...infer P] ? [...P, I] : [I]
type A = Flat<[1,2,3]> // [1,2,3]
type B = Flat<[1,[2,3], [4,[5,[6]]]]> // [1,2,3,4,5,6]
type C = Flat<[]> // []
// 瀹炵幇Flat
type Flat<T extends any[]> =
T extends [infer P, ...infer Q] ?
P extends any[] ? [...Flat<P>, ...Flat<Q>] : [P, ...Flat<Q>]
: [];
type A = Shift<[1,2,3]> // [2,3]
type B = Shift<[1]> // []
type C = Shift<[]> // []
// 瀹炵幇Shift
type Shift<T extends any[]> = T extends [infer P, ...infer Q] ? [...Q] : [];
type A = Repeat<number, 3> // [number, number, number]
type B = Repeat<string, 2> // [string, string]
type C = Repeat<1, 1> // [1, 1]
type D = Repeat<0, 0> // []
// 瀹炵幇Repeat
type Repeat<T, C, R extends any[] = []> =
R[\'length\'] extends C ? R : Repeat<T, C, [...R, T]>
type A = ReverseTuple<[string, number, boolean]> // [boolean, number, string]
type B = ReverseTuple<[1,2,3]> // [3,2,1]
type C = ReverseTuple<[]> // []
// 瀹炵幇ReverseTuple
type ReverseTuple<T extends any[], A extends any[] = []> =
T extends [...infer Q, infer P] ?
A[\'length\'] extends T[\'length\'] ? A : ReverseTuple<Q, [...A, P]>
: A;
type A = UnwrapPromise<Promise<string>> // string
type B = UnwrapPromise<Promise<null>> // null
type C = UnwrapPromise<null> // Error
// 瀹炵幇UnwrapPromise
type UnwrapPromise<T> = T extends Promise<infer P> ? P : Error;
type A = LengthOfString<\'BFE.dev\'> // 7
type B = LengthOfString<\'\'> // 0
// 瀹炵幇LengthOfString
type LengthOfString<T extends string, A extends any[] = []> =
T extends `${infer P}${infer Q}` ? LengthOfString<Q, [1, ...A]> : A[\'length\']
type A = StringToTuple<\'BFE.dev\'> // [\'B\', \'F\', \'E\', \'.\', \'d\', \'e\',\'v\']
type B = StringToTuple<\'\'> // []
// 瀹炵幇
type StringToTuple<T extends string, A extends any[] = []> =
T extends `${infer K}${infer P}` ? StringToTuple<P, [...A, K]> : A;
type A = LengthOfTuple<[\'B\', \'F\', \'E\']> // 3
type B = LengthOfTuple<[]> // 0
// 瀹炵幇
type LengthOfTuple<T extends any[], R extends any[] = []> =
R[\'length\'] extends T[\'length\'] ? R[\'length\'] : LengthOfTuple<T, [...R, 1]>
type A = LastItem<[string, number, boolean]> // boolean
type B = LastItem<[\'B\', \'F\', \'E\']> // \'E\'
type C = LastItem<[]> // never
// 瀹炵幇LastItem
type LastItem<T> = T extends [...infer P, infer Q] ? Q : never;
type A = FirstItem<[string, number, boolean]> // string
type B = FirstItem<[\'B\', \'F\', \'E\']> // \'B\'
// 瀹炵幇FirstItem
type FirstItem<T> = T extends [infer P, ...infer Q] ? P : never;
type A = FirstChar<\'BFE\'> // \'B\'
type B = FirstChar<\'dev\'> // \'d\'
type C = FirstChar<\'\'> // never
// 瀹炵幇FirstChar
type FirstChar<T> = T extends `${infer P}${infer Q}` ? P : never;
type Foo = {
a: string
b: number
c: boolean
}
type A = MyPick<Foo, \'a\' | \'b\'> // {a: string, b: number}
type B = MyPick<Foo, \'c\'> // {c: boolean}
type C = MyPick<Foo, \'d\'> // Error
// 瀹炵幇MyPick<T, K>
type MyPick<T, K extends keyof T> = {
[Key in K]: T[Key]
}
type Foo = {
a: string
}
const a:Foo = {
a: \'BFE.dev\',
}
a.a = \'bigfrontend.dev\'
// OK
const b:MyReadonly<Foo> = {
a: \'BFE.dev\'
}
b.a = \'bigfrontend.dev\'
// Error
// 瀹炵幇MyReadonly
type MyReadonly<T> = {
readonly [K in keyof T]: T[K]
}
type Key = \'a\' | \'b\' | \'c\'
const a: Record<Key, string> = {
a: \'BFE.dev\',
b: \'BFE.dev\',
c: \'BFE.dev\'
}
a.a = \'bigfrontend.dev\' // OK
a.b = 123 // Error
a.d = \'BFE.dev\' // Error
type Foo = MyRecord<{a: string}, string> // Error
// 瀹炵幇MyRecord
type MyRecord<K extends number | string | symbol, V> = {
[Key in K]: V
}
type Foo = \'a\' | \'b\' | \'c\'
type A = MyExclude<Foo, \'a\'> // \'b\' | \'c\'
type B = MyExclude<Foo, \'c\'> // \'a\' | \'b
type C = MyExclude<Foo, \'c\' | \'d\'> // \'a\' | \'b\'
type D = MyExclude<Foo, \'a\' | \'b\' | \'c\'> // never
// 瀹炵幇 MyExclude<T, K>
type MyExclude<T, K> = T extends K ? never : T;
type Foo = \'a\' | \'b\' | \'c\'
type A = MyExtract<Foo, \'a\'> // \'a\'
type B = MyExtract<Foo, \'a\' | \'b\'> // \'a\' | \'b\'
type C = MyExtract<Foo, \'b\' | \'c\' | \'d\' | \'e\'> // \'b\' | \'c\'
type D = MyExtract<Foo, never> // never
// 瀹炵幇MyExtract<T, U>
type MyExtract<T, U> = T extends U ? T : never
type Foo = {
a: string
b: number
c: boolean
}
type A = MyOmit<Foo, \'a\' | \'b\'> // {c: boolean}
type B = MyOmit<Foo, \'c\'> // {a: string, b: number}
type C = MyOmit<Foo, \'c\' | \'d\'> // {a: string, b: number}
// 瀹炵幇MyOmit
type MyOmit<T, K extends number | string | symbol> = {
[Key in Exclude<keyof T, K>]: T[Key]
}
type MyOmit<T, K extends number | string | symbol> = Pick<T, Exclude<keyof T, K>>
type Foo = \'a\' | \'b\' | null | undefined
type A = MyNonNullable<Foo> // \'a\' | \'b\'
// 瀹炵幇NonNullable
type MyNonNullable<T> = T extends null | undefined ? never : T;
type Foo = (a: string, b: number, c: boolean) => string
type A = MyParameters<Foo> // [a:string, b: number, c:boolean]
type B = A[0] // string
type C = MyParameters<{a: string}> // Error
// 瀹炵幇MyParameters<T>
type MyParameters<T extends (...params: any[]) => any> =
T extends (...params: [...infer P]) => any ? P : never
class Foo {
constructor (a: string, b: number, c: boolean) {}
}
type C = MyConstructorParameters<typeof Foo>
// [a: string, b: number, c: boolean]
// 瀹炵幇MyConstructorParameters<T>
type MyConstructorParameters<T extends new (...params: any[]) => any> =
T extends new (...params: [...infer P]) => any ? P : never
type Foo = () => {a: string}
type A = MyReturnType<Foo> // {a: string}
// 瀹炵幇MyReturnType<T>
type MyReturnType<T extends (...params: any[]) => any> =
T extends (...params: any[]) => infer P ? P : never;
class Foo {}
type A = MyInstanceType<typeof Foo> // Foo
type B = MyInstanceType<() => string> // Error
// 瀹炵幇MyInstanceType<T>
type MyInstanceType<T extends new (...params: any[]) => any> =
T extends new (...params: any[]) => infer P ? P : never;
function Foo(this: {a: string}) {}
function Bar() {}
type A = MyThisParameterType<typeof Foo> // {a: string}
type B = MyThisParameterType<typeof Bar> // unknown
// 瀹炵幇MyThisParameterType<T>
type MyThisParameterType<T extends (this: any, ...params: any[]) => any> =
T extends (this: infer P, ...params: any[]) => any ? P : unknown;
type Foo = [string, number, boolean]
type Bar = TupleToUnion<Foo> // string | number | boolean
// 瀹炵幇TupleToUnion<T>
type TupleToUnion<T extends any[], R = T[0]> =
T extends [infer P, ...infer Q] ? TupleToUnion<Q, R | P> : R;
// 鍏朵粬鍥炵瓟
type TupleToUnion<T extends any[]> = T[number]
type Foo = {
a: string
b: number
c: boolean
}
// below are all valid
const a: MyPartial<Foo> = {}
const b: MyPartial<Foo> = {
a: \'BFE.dev\'
}
const c: MyPartial<Foo> = {
b: 123
}
const d: MyPartial<Foo> = {
b: 123,
c: true
}
const e: MyPartial<Foo> = {
a: \'BFE.dev\',
b: 123,
c: true
}
// 瀹炵幇MyPartial<T>
type MyPartial<T> = {
[K in keyof T]?: T[K]
}
// all properties are optional
type Foo = {
a?: string
b?: number
c?: boolean
}
const a: MyRequired<Foo> = {}
// Error
const b: MyRequired<Foo> = {
a: \'BFE.dev\'
}
// Error
const c: MyRequired<Foo> = {
b: 123
}
// Error
const d: MyRequired<Foo> = {
b: 123,
c: true
}
// Error
const e: MyRequired<Foo> = {
a: \'BFE.dev\',
b: 123,
c: true
}
// valid
// 瀹炵幇MyRequired<T>
type MyRequired<T> = {
[K in keyof T]-?: T[K]
}
type A = LastChar<\'BFE\'> // \'E\'
type B = LastChar<\'dev\'> // \'v\'
type C = LastChar<\'\'> // never
// 瀹炵幇FirstChar<T>
type LastChar<T extends string, A extends string[] = []> =
T extends `${infer P}${infer Q}` ? LastChar<Q, [...A, P]> :
A extends [...infer L, infer R] ? R : never
;
// https://stackoverflow.com/questions/53984650/typescript-never-type-inconsistently-matched-in-conditional-type
// https://www.typescriptlang.org/docs/handbook/advanced-types.html#v
type A = IsNever<never> // true
type B = IsNever<string> // false
type C = IsNever<undefined> // false
// 瀹炵幇IsNever<T>
type IsNever<T> = [T] extends [never] ? true : false;
type A = KeyToUnion<{
a: string;
b: number;
c: symbol;
}>
// \'a\' | \'b\' | \'c\'
// 瀹炵幇KeyToUnion
type KeyToUnion<T> = {
[K in keyof T]: K;
}[keyof T]
type A = ValuesToUnion<{
a: string;
b: number;
c: symbol;
}>
// string | number | symbol
// ValuesToUnion
type ValuesToUnion<T> = T[keyof T]
type IsAny<T> = 0 extends (T & 1) ? true : false;
type IsNever<T> = [T] extends [never] ? true : false;
type TwoAny<A, B> = IsAny<A> extends IsAny<B> ? IsAny<A> : false;
type TwoNever<A, B> = IsNever<A> extends IsNever<B> ? IsNever<A> : false;
type SingleAny<A, B> = IsAny<A> extends true ? true : IsAny<B>
type SingleNever<A, B> = IsNever<A> extends true ? true : IsNever<B>
type FindIndex<T extends any[], E, A extends any[] = []> =
T extends [infer P, ...infer Q] ?
TwoAny<P, E> extends true ?
A[\'length\']
:
TwoNever<P, E> extends true ?
A[\'length\']
:
SingleAny<P, E> extends true ?
FindIndex<Q, E, [1, ...A]>
:
SingleNever<P, E> extends true ?
FindIndex<Q, E, [1, ...A]>
:
P extends E ? A[\'length\'] : FindIndex<Q, E, [1, ...A]>
:
never
type A = Trim<\' BFE.dev\'> // \'BFE\'
type B = Trim<\' BFE. dev \'> // \'BFE. dev\'
type C = Trim<\' BFE . dev \'> // \'BFE . dev\'
type StringToTuple<T extends string, A extends any[] = []> =
T extends `${infer K}${infer P}` ? StringToTuple<P, [...A, K]> : A;
type TupleToString<T extends any[], S extends string = \'\', A extends any[] = []> =
A[\'length\'] extends T[\'length\'] ? S : TupleToString<T, `${S}${T[A[\'length\']]}`, [1, ...A]>
type Trim<T extends string, A extends any[] = StringToTuple<T>> =
A extends [infer P, ...infer Q] ?
P extends \' \' ?
Trim<T, Q>
:
A extends [...infer M, infer N] ?
N extends \' \' ?
Trim<T, M>
:
TupleToString<A>
:
\'\'
:
\'\';
杩樻湁鏇村 UnionToTuple
, IntersectionToUnion
?
以上是关于TypeScript闈㈣瘯棰樻€荤粨的主要内容,如果未能解决你的问题,请参考以下文章