Created
August 4, 2017 09:32
-
-
Save minoki/9c0e7a5bd4efd889339c9931c1d51c76 to your computer and use it in GitHub Desktop.
TypeScriptの正規表現にマシな型をつける ref: http://qiita.com/mod_poppo/items/4549dcfa16ae99ebf126
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let m = str.match(/(a)(b)?/); | |
if (m) { | |
let a: string = m[1]; | |
let b: string = m[2]; // 本当は string | undefined | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let str = "x\\yz"; | |
let t = str.replace(/\\(.)/, (m, s) => s.toUpperCase()); | |
// s は any 型なので、仮に s.toUpper() と書いてもエラーにならない |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface String { | |
match<captures extends SList>(regexp: TypedRegExp<captures>): TypedRegExpMatchArray<captures> | null; | |
replace<a0, a1, a2>(searchValue: TypedRegExp<SCons<a0, SCons<a1, SCons<a2, SNil>>>>, replacer: (match: string, a0: a0, a1: a1, a2: a2, offset: number, string: string) => string): string; | |
replace<a0, a1>(searchValue: TypedRegExp<SCons<a0, SCons<a1, SNil>>>, replacer: (match: string, a0: a0, a1: a1, offset: number, string: string) => string): string; | |
replace<a0>(searchValue: TypedRegExp<SCons<a0, SNil>>, replacer: (match: string, a0: a0, offset: number, string: string) => string): string; | |
replace(searchValue: TypedRegExp<SNil>, replacer: (match: string, offset: number, string: string) => string): string; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type SNil = { | |
"tag": "Nil"; | |
}; | |
type SCons<a, b extends SList> = { | |
"tag": "Cons"; | |
"head": a; | |
"tail": b; | |
}; | |
type SList = SNil | { | |
"tag": "Cons"; | |
"head": any; | |
"tail": SList; | |
}; | |
// type SList = SNil | SCons<any, SList>; とは書けないが、上のようには書ける | |
// リストの連結 | |
type Concat<a extends SList, b extends SList> = { | |
"Nil": b; | |
"Cons": SCons<a["head"], Concat<a["tail"], b>>; | |
}[a["tag"]]; | |
// リストの要素を全て undefined で置き換える | |
type FillUndefined<a extends SList> = { | |
"Nil": SNil; | |
"Cons": SCons<undefined, FillUndefined<a["tail"]>>; | |
}[a["tag"]]; | |
// リストの要素に対して | undefined を行う | |
type MaybeUndefined<a extends SList> = { | |
"Nil": SNil; | |
"Cons": SCons<a["head"] | undefined, MaybeUndefined<a["tail"]>>; | |
}[a["tag"]]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// error TS2322: Type '0' is not assignable to type 'SCons<"a", SCons<"b", SCons<"c", SCons<"d", SNil>>>>'. | |
let x : Concat<SCons<"a", SCons<"b", SNil>>, SCons<"c", SCons<"d", SNil>>> = 0; | |
// error TS2322: Type '0' is not assignable to type 'SCons<undefined, SCons<undefined, SCons<undefined, SNil>>>'. | |
let y : FillUndefined<SCons<string, SCons<number, SCons<null, SNil>>>> = 0; | |
// error TS2322: Type '0' is not assignable to type 'SCons<string | undefined, SCons<number | undefined, SCons<null | undefined, SNil>>>'. | |
let z : MaybeUndefined<SCons<string, SCons<number, SCons<null, SNil>>>> = 0; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type ToTuple5<a0, a1, a2, a3, a4, a extends SList> = { | |
"Nil": [a0, a1, a2, a3, a4]; | |
"Cons": [a0, a1, a2, a3, a4, a["head"]]; // a["tail"] is dropped... | |
}[a["tag"]]; | |
type ToTuple4<a0, a1, a2, a3, a extends SList> = { | |
"Nil": [a0, a1, a2, a3]; | |
"Cons": ToTuple5<a0, a1, a2, a3, a["head"], a["tail"]>; | |
}[a["tag"]]; | |
type ToTuple3<a0, a1, a2, a extends SList> = { | |
"Nil": [a0, a1, a2]; | |
"Cons": ToTuple4<a0, a1, a2, a["head"], a["tail"]>; | |
}[a["tag"]]; | |
type ToTuple2<a0, a1, a extends SList> = { | |
"Nil": [a0, a1]; | |
"Cons": ToTuple3<a0, a1, a["head"], a["tail"]>; | |
}[a["tag"]]; | |
type ToTuple1<a0, a extends SList> = { | |
"Nil": [a0]; | |
"Cons": ToTuple2<a0, a["head"], a["tail"]>; | |
}[a["tag"]]; | |
type ToTuple<a extends SList> = { | |
"Nil": []; | |
"Cons": ToTuple1<a["head"], a["tail"]>; | |
}[a["tag"]]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type TypedRegExpExecArray<captures extends SList> = ToTuple<SCons<string, captures>> & {index: number; input: string}; | |
type TypedRegExpMatchArray<captures extends SList> = ToTuple<SCons<string, captures>> & {index?: number; input?: string}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type ToFunction5<r, a0, a1, a2, a3, a4, a extends SList> = { | |
"Nil": (a0: a0, a1: a1, a2: a2, a3: a3, a4: a4) => r; | |
"Cons": (a0: a0, a1: a1, a2: a2, a3: a3, a4: a4, a5: a["head"]) => r; // a["tail"] is dropped... | |
}[a["tag"]]; | |
type ToFunction4<r, a0, a1, a2, a3, a extends SList> = { | |
"Nil": (a0: a0, a1: a1, a2: a2, a3: a3) => r; | |
"Cons": ToFunction5<r, a0, a1, a2, a3, a["head"], a["tail"]>; | |
}[a["tag"]]; | |
type ToFunction3<r, a0, a1, a2, a extends SList> = { | |
"Nil": (a0: a0, a1: a1, a2: a2) => r; | |
"Cons": ToFunction4<r, a0, a1, a2, a["head"], a["tail"]>; | |
}[a["tag"]]; | |
type ToFunction2<r, a0, a1, a extends SList> = { | |
"Nil": (a0: a0, a1: a1) => r; | |
"Cons": ToFunction3<r, a0, a1, a["head"], a["tail"]>; | |
}[a["tag"]]; | |
type ToFunction1<r, a0, a extends SList> = { | |
"Nil": (a0: a0) => r; | |
"Cons": ToFunction2<r, a0, a["head"], a["tail"]>; | |
}[a["tag"]]; | |
type ToFunction<r, a extends SList> = { | |
"Nil": () => r; | |
"Cons": ToFunction1<r, a["head"], a["tail"]>; | |
}[a["tag"]]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// interface TypedRegExp<> extends RegExp では 'exec' の型が違うと言われて怒られた、ので交差型を使う | |
type TypedRegExp<captures extends SList> = { | |
exec(string: string): TypedRegExpExecArray<captures> | null; | |
} & RegExp; /* RegExp が & の後でないとメソッドの型を上書きできないようなので注意 */ | |
interface String { | |
match<captures extends SList>(regexp: TypedRegExp<captures>): TypedRegExpMatchArray<captures> | null; | |
replace<captures extends SList>(searchValue: TypedRegExp<captures>, replacer: ToFunction<string, SCons<string, Concat<captures, SCons<number, SCons<string, SNil>>>>>): string; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let str = "abc" | |
let m = str.match(/(a)(b)?/ as TypedRegExp<SCons<string, SCons<string | undefined, SNil>>>); | |
if (m) { | |
let a: string = m[1]; | |
let b: string = m[2]; // --strictNullChecks でエラー | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let str = "x\\yz"; | |
let t = str.replace(/\\(.)/ as TypedRegExp<SCons<string, SNil>>, (m, s) => s.toUpper()); // エラーにならない! | |
console.log(t); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment