ããããã£ãåãªãæååïŒãŸãã¯æååã®ã»ããïŒã§ã¯ãªãããã¿ãŒã³ã«äžèŽããå¿ èŠãããå ŽåããããŸãã
let fontStyle: 'normal' | 'italic' = 'normal'; // already available in master
let fontColor: /^#([0-9a-f]{3}|[0-9a-f]{6})$/i = '#000'; // my suggestion
JavaScriptã§ã¯ãDOMããŒããããŸããŸãªãµãŒãããŒãã£ã©ã€ãã©ãªã®cssã¹ã¿ã€ã«ã®åæ ãªã©ãcssè¡šèšã§è²ã®å€ãæ ŒçŽããã®ãäžè¬çã§ãã
ã©ãæããŸããïŒ
ãããç§ã¯ãããDefinitelyTypedãä»ããŠã³ãŒãã³ã°ããã®ãèŠãŸããã ãµãŒãã¹ã¬ã€ã€ãŒã§
äž»ãªåé¡ã¯æ¬¡ã®ãšããã§ãã
"cat"
ã "dog"
ãããã³"fish"
ã³ã³ãåºåããªã¹ããå¿
èŠãªå Žåã¯ã /dog|cat|fish(,(dog|cat|fish))*/
ããã«èšè¿°ããå¿
èŠããããŸãã"cat"
ã "dog
"ãããã³"fish"
æååãªãã©ã«åãèšè¿°ããåããã§ã«ããå Žåããããããã®æ£èŠè¡šçŸã«çµ±åããã«ã¯ã©ãããã°ããã§ããïŒããã«é¢ãã巚倧ãª+ 1ãZipCodeãSSNãONetãããã«é¢ããä»ã®å€ãã®ãŠãŒã¹ã±ãŒã¹ã
åãåé¡ã«çŽé¢ããŸãããããŸã å®è£
ãããŠããªãããšãããããŸãããããããããã®åé¿çã圹ç«ã€ã§ãããã
http://stackoverflow.com/questions/37144672/guid-uuid-type-inââ-typescript
@mhegazyãææ¡ããããã«ãç§ã¯ããã«ç§ã®ææ¡ïŒïŒ8665ïŒã眮ããŸãã å宣èšã§åçŽãªæ€èšŒé¢æ°ãèš±å¯ããã®ã¯ã©ãã§ããïŒ ãããªæãïŒ
type Integer(n:number) => String(n).macth(/^[0-9]+$/)
let x:Integer = 3 //OK
let y:Integer = 3.6 //wrong
type ColorLevel(n:number) => n>0 && n<= 255
type RGB = {red:ColorLevel, green:ColorLevel, blue:ColorLevel};
let redColor:RGB = {red:255, green:0, blue:0} //OK
let wrongColor:RGB = {red:255, green:900, blue:0} //wrong
type Hex(n:string) => n.match(/^([0-9]|[A-F])+$/)
let hexValue:Hex = "F6A5" //OK
let wrongHexValue:Hex = "F6AZ5" //wrong
ã¿ã€ããåãå ¥ããããšãã§ããå€ã¯ãé¢æ°ãã©ã¡ãŒã¿ãŒã¿ã€ããšé¢æ°è©äŸ¡èªäœã«ãã£ãŠæ±ºå®ãããŸãã ããã¯ïŒ7982ã解決ããŸãã
@rylphs +1ããã«ãããTypeScriptã¯éåžžã«åŒ·åã«ãªããŸã
ãµãã¿ã€ãã³ã°ã¯_regex-validatedstring types_ã§ã©ã®ããã«æ©èœããŸããïŒ
let a: RegExType_1
let b: RegExType_2
a = b // Is this allowed? Is RegExType_2 subtype of RegExType_1?
b = a // Is this allowed? Is RegExType_1 subtype of RegExType_2?
ããã§ã RegExType_1
ãšRegExType_2
ã¯_æ£èŠè¡šçŸã§æ€èšŒãããæååå_ã§ãã
ç·šéïŒãã®åé¡ã¯å€é åŒæéã§è§£æ±ºã§ããããã§ãïŒæ£èŠè¡šçŸã®å å«åé¡ãåç §ïŒã
TypeStyleã«ã圹ç«ã¡ãŸãïŒ https ïŒ
JSXã§ã¯ã @ RyanCavanaughãšç§ã¯ã人ã
ãaria-
ïŒããã³å Žåã«ãã£ãŠã¯data-
ïŒå±æ§ãè¿œå ããã®ãèŠãŠããŸããã 誰ããå®éã«ãã£ãããªãŒã«ãšããŠDefinitelyTypedã«æååã€ã³ããã¯ã¹çœ²åãè¿œå ããŸããã ãã®ããã®æ°ããã€ã³ããã¯ã¹çœ²åã圹ç«ã€ã§ãããã
interface IntrinsicElements {
// ....
[attributeName: /aria-\w+/]: number | string | boolean;
}
ããéçºè
ã¯ãã®åŸãåãªãæååããæå®ãããå€ãå¿
èŠãšãããšãäŸããããããããŸãããåçŽãªæååãªãã©ã«äŸãã°CSSã®è²ãé»åã¡ãŒã«ãé»è©±çªå·ãéµäŸ¿çªå·ãã®åéåãšããŠããããåæããããšã¯ã§ããŸããéæ©æ¡åŒµåãããªã©JSONã¹ããŒãä»æ§ã¯ãã©ã®äžè¬JSONãªããžã§ã¯ãã®ã¹ããŒããèšè¿°ããããã«äœ¿çšãããã®ã¯ãTSã¿ã€ãã·ã¹ãã ã®èŠ³ç¹ããregex-validated string type
ããã³regex-validated string type of index
ãšåŒã°ããå¯èœæ§ã®ããpatternããã³patternPropertiesãæã£ãŠããŸãã
éçºè ã«ãJSONã¹ããŒãã«äžæ©è¿ãåã·ã¹ãã ãæäŸããŸããããã¯ãéçºè ãäžè¬çã«äœ¿çšããå¿ èŠã«å¿ããŠæååæ€èšŒãã§ãã¯ãå¿ããªãããã«ããŸãã
ãã®æ©èœã®å®è£ ã¯ã次ã®4ã€ã®éšåã§æ§æãããŠããŸãã
type CssColor = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
type Email = /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i;
type Gmail = /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@gmail\.com$/i;
let fontColor: /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
åãã§ãããããèªã¿ããã
let fontColor: CssColor;
interface UsersCollection {
[email: /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i]: User;
}
åãã§ãããããèªã¿ããã
interface UsersCollection {
[email: Email]: User;
}
setFontColorFromString(color: string) {
fontColor = color;// compile time error
if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(color)) {
fontColor = color;// correct
}
}
ãšåã
setFontColorFromString(color: string) {
fontColor = color;// compile time error
if (!(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(color))) return;
fontColor = color;// correct
}
èªã¿ããããåäžãããããã«å®çŸ©ãããåã䜿çšãã
setFontColorFromString(color: string) {
fontColor = color;// compile time error
if (CssColor.test(color)) {
fontColor = color;// correct
}
}
ãšåã
setFontColorFromString(color: string) {
fontColor = color;// compile time error
if (!(CssColor.test(color))) return;
fontColor = color;// correct
}
let collection: UsersCollection;
getUserByEmail(email: string) {
collection[email];// type is any
if (/^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i.test(email)) {
collection[email];// type is User
}
}
ãšåã
let collection: UsersCollection;
getUserByEmail(email: string) {
collection[email];// type is any
if (!(/^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i.test(email))) return;
collection[email];// type is User
}
èªã¿ããããåäžãããããã«å®çŸ©ãããåã䜿çšãã
let collection: UsersCollection;
getUserByEmail(email: string) {
collection[email];// type is any
if (Email.test(email)) {
collection[email];// type is User
}
}
ãšåã
let collection: UsersCollection;
getUserByEmail(email: string) {
collection[email];// type is any
if (!(Email.test(email))) return;
collection[email];// type is User
}
let email: Email;
let gmail: Gmail;
email = '[email protected]';// correct
email = '[email protected]';// correct
gmail = '[email protected]';// compile time error
gmail = '[email protected]';// correct
gmail = email;// obviously compile time error
email = gmail;// unfortunately compile time error too
æ®å¿µãªããããã®èšäºã«ããããã©ãŒãã³ã¹ãžã®å€§ããªåœ±é¿ãªãã«ãããæ£èŠè¡šçŸãå¥ã®æ£èŠè¡šçŸã®ãµãã¿ã€ãã§ãããã©ããã確èªããããšã¯ã§ããŸããã ãããã£ãŠãå¶éããå¿ èŠããããŸãã ãã ãã次ã®åé¿çããããŸãã
// explicit cast
gmail = <Gmail>email;// correct
// type guard
if (Gmail.test(email)) {
gmail = email;// correct
}
// another regex subtype declaration
type Gmail = Email & /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@gmail\.com$/i;
gmail = email;// correct
æ®å¿µãªããã string
å€æ°ã®regex-validated
string
å€æ°ãžã®å²ãåœãŠãå¶éããå¿
èŠããããŸããããã¯ãã³ã³ãã€ã«æã«æ£èŠè¡šçŸãšäžèŽãããšããä¿èšŒããªãããã§ãã
let someEmail = '[email protected]';
let someGmail = '[email protected]';
email = someEmail;// compile time error
gmail = someGmail;// compile time error
ãã ããããã«ç€ºãããã«ãæ瀺çãªãã£ã¹ãã¬ãŒããŸãã¯åã¬ãŒãã䜿çšã§ã
幞ããªããšã«ãæååãªãã©ã«ã®å Žåã¯ããã§ã¯ãããŸãããæååãªãã©ã«ã䜿çšããŠãããšãã«ããã®å€ãæ£èŠè¡šçŸãšäžèŽããããšã確èªã§ããããã§ãã
let someEmail: '[email protected]' = '[email protected]';
let someGmail: '[email protected]' = '[email protected]';
email = someEmail;// correct
gmail = someGmail;// correct
ã€ã³ããã¯ã¹ã®regex-validated type
ã®åçŽãªã±ãŒã¹ã«ã€ããŠã¯ãã€ã³ããã¯ã¹ã¿ã€ãã®ã¿ã€ãgurardãåç
§ããŠãã ããã
ãããããã£ãšè€éãªã±ãŒã¹ããããããããŸããïŒ
type Email = /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i;
type Gmail = /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@gmail\.com$/i;
interface UsersCollection {
[email: Email]: User;
[gmail: Gmail]: GmailUser;
}
let collection: UsersCollection;
let someEmail = '[email protected]';
let someGmail = '[email protected]';
collection['[email protected]'];// type is User
collection['[email protected]'];// type is User & GmailUser
collection[someEmail];// unfortunately type is any
collection[someGmail];// unfortunately type is any
// explicit cast is still an unsafe workaround
collection[<Email> someEmail];// type is User
collection[<Gmail> someGmail];// type is GmailUser
collection[<Email & Gmail> someGmail];// type is User & GmailUser
ãªãã©ã«ã«ã¯ãã®ãããªåé¡ã¯ãããŸããã
let collection: UsersCollection;
let someEmail: '[email protected]' = '[email protected]';
let someGmail: '[email protected]' = '[email protected]';
collection[someEmail];// type is User
collection[someGmail];// type is User & GmailUser
ãã ããå€æ°ã®å Žåã次ã®ããçŸå®çãªäŸã®ããã«ãã¿ã€ãã¬ãŒãã䜿çšããã®ãæåã®ãªãã·ã§ã³ã§ãã
getUserByEmail(email: string) {
collection[email];// type is any
if (Email.test(email)) {
collection[email];// type is User
if (Gmail.test(email)) {
collection[email];// type is User & GmailUser
}
}
if (Gmail.test(email)) {
collection[email];// type is GmailUser
}
}
ãããã Gmail
åã«å¯ŸããŠããé©åãªå®çŸ©ã䜿çšãããšãå¥ã®åã®çµã蟌ã¿ãè¡ãããŸãã
type Gmail = Email & /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@gmail\.com$/i;
getUserByEmail(email: string) {
collection[email];// type is any
if (Email.test(email)) {
collection[email];// type is User
if (Gmail.test(email)) {
collection[email];// type is User & GmailUser
}
}
if (Gmail.test(email)) {
collection[email];// type is User & GmailUser
}
}
å®éã«ã¯ãäžè¬çãªã¿ã€ããšregex-validated
ã¿ã€ãã¯å®éã«ã¯ç°ãªããããcorrecltyããããã®åéåãšå
±ééšåãåŠçããæ¹æ³ã®ã«ãŒã«ãå¿
èŠã§ãã
type Regex_1 = / ... /;
type Regex_2 = / ... /;
type NonRegex = { ... };
type test_1 = Regex_1 | Regex_2;// correct
type test_2 = Regex_1 & Regex_2;// correct
type test_3 = Regex_1 | NonRegex;// correct
type test_4 = Regex_1 & NonRegex;// compile time error
if (test_1.test(something)) {
something;// type is test_1
// something matches Regex_1 OR Regex_2
}
if (test_2.test(something)) {
something;// type is test_2
// something matches Regex_1 AND Regex_2
}
if (test_3.test(something)) {
something;// type is Regex_1
} else {
something;// type is NonRegex
}
ãžã§ããªãã¯ã«ã¯ç¹å¥ãªã±ãŒã¹ã¯ãªãã®ã§ã regex-validated
åã¯ãéåžžã®åãšåãããã«ãžã§ããªãã¯ã§äœ¿çšã§ããŸãã
以äžã®ãããªå¶çŽã®ãããžã§ããªãã¯ã¹ã®å Žåã regex-validated
åã¯æååã®ããã«åäœããŸãã
class Something<T extends String> { ... }
let something = new Something<Email>();// correct
éåžžã®ã¿ã€ããšã¯ç°ãªãã regex-validated
ã¯æŸåºã«ããããã®åœ±é¿ãåãŒããŸãã
type Regex_1 = / ... /;
type Regex_2 = / ... /;
type NonRegex = { ... };
type test_1 = Regex_1 | Regex_2;
type test_2 = Regex_1 & Regex_2;
type test_3 = Regex_1 | NonRegex;
type test_4 = Regex_1 & NonRegex;
if (test_1.test(something)) {
/* ... */
}
if (test_2.test(something)) {
/* ... */
}
if (test_3.test(something)) {
/* ... */
} else {
/* ... */
}
ã³ã³ãã€ã«ãããŸãïŒ
var Regex_1 = / ... /;
var Regex_2 = / ... /;
if (Regex_1.test(something) || Regex_2.test(something)) {
/* ... */
}
if (Regex_1.test(something) && Regex_2.test(something)) {
/* ... */
}
if (Regex_1.test(something)) {
/* ... */
} else {
/* ... */
}
ãã®æ©èœã¯ããããå£ãå¯èœæ§ãããã±ãŒã¹ã®ã¿ãããã regex-validated
ã¿ã€ããéåžžã®ã¿ã€ããšã¯ç°ãªã圱é¿ãäžããããšã«é¢é£ããŠãããããäºææ§ã«åé¡ã¯ãããŸããããããã£ãŠãããã¯æå¹ãªTSã³ãŒãã§ãã
type someType = { ... };
var someType = { ... };
以äžã®ã³ãŒããããã§ãªãå ŽåïŒ
type someRegex = / ... /;
var someRegex = { ... };
ãããã2çªç®ã¯ãã§ã«ç¡å¹ã§ããããå¥ã®çç±ïŒå宣èšãééã£ãŠããïŒãåå ã§ãã
ãããã£ãŠããã®åãregex-validated
å Žåã«åããŠãåãšåãååã®å€æ°ã®å®£èšãå¶éããå¿
èŠããããŸãã
ç§ãããããèŠéããããšãèªç±ã«ææããŠãã ããã ãã®ææ¡ãæ°ã«å ¥ã£ããããããã«ããŒãããã¹ããäœæããŠãPRãšããŠè¿œå ããŠã¿ãŠãã ããã
regex-validated
ã¿ã€ãã®å
±ééšåãšåéåã®ããã€ãã®ã±ãŒã¹ãææããã®ãå¿ããŸããããææ°ã®ãã¹ãã±ãŒã¹ã§ãããã説æããŸããã ãã®å°ããªå€æŽãåæ ããããã«Design proposal
ãæŽæ°ããå¿
èŠããããŸããïŒ
@Igmat ãããªãã®ãã¶ã€ã³ææ¡ã«ã€ããŠã®è³ªåïŒæŸåºã®æŠèŠã«ã€ããŠè©³ãã
@alexanderbird ãã¯ããä»ã®ã¿ã€ãã¯æŸåºã«åœ±é¿ãäžããŸããã æåã¯ã regex-validated
ã§ããããªããšæã£ãŠããã®ã§ãææ¡ãäœæããææ¡ãããæ§æã§éãã§ã¿ãŸããã
æåã®ã¢ãããŒãã¯æ¬¡ã®ãããªãã®ã§ããã
let fontColor: /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
fontColor = "#000";
ãã®ïŒ
type CssColor: /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
let fontColor: CssColor;
fontColor = "#000";
"#000"
ã¯ã³ã³ãã€ã«æã«ãã§ãã¯ã§ãããããåé¡ã¯ãªããå€æŽãçºè¡ããå¿
èŠããããŸããã
ãã ãã䟿å©ã«ããããã«ã string
ããregex-validated
ã¿ã€ããžã®çµã蟌ã¿ãåŠçããå¿
èŠããããŸãã ã ããç§ã¯ä»¥åã®äž¡æ¹ã®ã»ããã¢ããã§ããã«ã€ããŠèããŸããïŒ
let someString: string;
if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(someString)) {
fontColor = someString; // Ok
}
fontColor = someString; // compile time error
ãããã£ãŠãæ£èŠè¡šçŸã¯ããŸãèªã¿ã«ããããã¹ãŠã®å Žæã«ã³ããŒããå¿
èŠãããããããŠãŒã¶ãŒãç°¡åã«ééããå¯èœæ§ãããããšãé€ãã°ãemitã«ã¯åœ±é¿ãããåé¡ãªãããã«èŠããŸãã ãããããã®ç¹å®ã®ã±ãŒã¹ã§ã¯ã type
åäœãå€æŽãããããåªããŠããããã§ãã
ããããããããç§ã¯ãã®ãããªãã®ã«æ°ã¥ããŸããïŒ
let someString: string;
let email: /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/I;
if (/^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i.test(someString)) {
email = someString; // Ok
}
email = someString; // compile time error
æªå€¢ã§ãã ãããŠãããã¯äº€å·®ç¹ãåéåããªããŠãã§ãã ãããã£ãŠããã®ãããªäºæ
ãçºçããªãããã«ããã«ã¯ãææ¡ã«ç€ºãããŠããããã«ã type
æŸåºããããã«å€æŽããå¿
èŠããããŸãã
@DanielRosenwasser ããã®ææ¡ã«å¯Ÿãããã£ãŒãããã¯ããé¡ãããŸãã ãŸããå¯èœã§ããã°ãããã§åç
§ãããŠãããã¹ãã«ã€ããŠãã©ãã§ããããã
ãã®æ©èœã®å®è£
ãæ¬åœã«æäŒãããã®ã§ãããæéãããããŸãïŒ tsc
ã¯éåžžã«è€éãªãããžã§ã¯ãã§ãããå
éšã§ã©ã®ããã«æ©èœããããç解ããããã«äœæ¥ããå¿
èŠããããŸãïŒããã®ææ¡ãå®è£
ããæºåãã§ããŠããããå¥ã®èšèªèšèšããžã§ã³ãŸãã¯ãã®ä»ã®çç±ã«ããããã®æ¹æ³ã§å®è£
ããããã®æ©èœãæåŠããŸãã
ãã@Igmat ãç§ãæåã«å°ããã¹ãã ã£ãããšãããã€ããããšæããŸã
ããããããªãæŸåºããã®ã«äœããã®å€æŽãå¿ èŠãªã®ããç§ã«ã¯ãŸã ããããŸããããŸããã¿ã€ãã«åºã¥ããæŸåºã¯åãå ¥ããããªããšæããŸãã ããã§ç§ãã¡ã®éç®æšããã§ãã¯ããŠãã ããã
ç§ãæèµ·ãã¹ããã1ã€ã®åé¡ã¯ãåŸæ¹åç §ã䜿çšããæ£èŠè¡šçŸã®åé¡ã§ãã ç§ã®ç解ïŒããã³çµéšïŒã¯ãæ£èŠè¡šçŸã®åŸæ¹åç §ã«ãããå ¥åã«å¯ŸããŠææ°é¢æ°çãªæéã§ãã¹ãã匷å¶çã«å®è¡ã§ããããšã§ãã ããã¯ã³ãŒããŒã±ãŒã¹ã§ããïŒ ãã¶ããã§ãããã¯ç§ãäžè¬çã«é¿ããããã®ã§ãã ãšãã£ã¿ãŒã®ã·ããªãªã§ã¯ãããå Žæã§ã®ã¿ã€ããã§ãã¯ã«ãããæéãæå°éã§ãããããããã¯ç¹ã«éèŠã§ãã
ãã1ã€ã®åé¡ã¯ãTypeScriptã³ã³ãã€ã©ãå®è¡ããããšã³ãžã³ã«äŸåããããããããå®è¡ããããã«ã«ã¹ã¿ã æ£èŠè¡šçŸãšã³ãžã³ãæ§ç¯ããå¿
èŠãããããšã§ãã ããšãã°ãTC39ã¯ã .
ãæ¹è¡ãšäžèŽã§ããããã«ãæ°ããs
ãã©ã°ãå«ããããã«ç§»åããŠããŸãã ESXXXXãšãããããµããŒãããå€ãã©ã³ã¿ã€ã ãšã®éã«ã¯äžäžèŽããããŸãã
@ igmat-å®è¡æã«æ£èŠè¡šçŸãééããããŸããã ãã ãããã®æ©èœã圹ç«ã€ããã«å¿ èŠã ãšã¯æããŸããïŒ @DanielRosenwasserãèšã£ãããšãããããšããšã«ããæ¿èªãããªãå¯èœæ§ããããŸãïŒã ããªããèšã£ã
ãã ããæååããæ£èŠè¡šçŸã§æ€èšŒãããã¿ã€ããžã®ãããŒã€ã³ã°ãåŠçããŠã䟿å©ã«ããå¿ èŠããããŸãã
ããã¯ãåçæååããæ£èŠè¡šçŸã§æ€èšŒãããã¿ã€ãã«çµã蟌ãå Žåã«ã®ã¿åœãŠã¯ãŸããšæããŸãã ããã¯éåžžã«è€éã«ãªããŸãã ãã®åçŽãªå Žåã§ãïŒ
function foo(bar: number) {
let baz: /prefix:\d+/ = 'prefix:' + number;
}
ã¿ã€ããäžèŽãããã©ããã¯ããããŸãã-æ°å€ãè² ã®å Žåã¯ã©ããªããŸããïŒ ãããŠãæ£èŠè¡šçŸãããè€éã«ãªãã«ã€ããŠãããã¯ã©ãã©ãä¹±éã«ãªããŸãã ãããæ¬åœã«å¿
èŠãªå Žåã¯ããåè£éïŒ type Baz = /prefix:{number}/
...ããèš±å¯ãããããããŸããããããã«è¡ã䟡å€ããããã©ããã¯ããããŸããã
代ããã«ãæååãªãã©ã«ã®ã¿ãæ£èŠè¡šçŸã§æ€èšŒãããåã«å²ãåœãŠãããšãèš±å¯ããå Žåãç®æšã®éäžã«å°éããå¯èœæ§ããããŸãã
次ã®ããšãèæ ®ããŠãã ããã
type Color = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
let foo: Color = '#000000';
let bar: Color = '#0000'; // Error - string literal '#0000' is not assignable to type 'Color'; '#0000' does not match /^#([0-9a-f]{3}|[0-9a-f]{6})$/i
let baz: Color = '#' + config.userColorChoice; // Error - type 'string' is not assignable to type 'regex-validated-string'
ããã¯å®è¡å¯èœãªä»£æ¿æ¡ã ãšæããŸããïŒ
@DanielRosenwasser ãç§ã¯èšèšç®æšã泚ææ·±ãèªã¿ãŸãããããªããæ£ããç解ããŠããã°ãåé¡ã¯éç®æšïŒ5ã®éåã§ãã
ããããããã¯éåã§ã¯ãªããæ§æã®æ¹åãšããŠç§ã«ã¯æããŸãã ããšãã°ã以åã¯æ¬¡ã®ããã«ãªããŸããã
const emailRegex = /.../;
/**
* assign it only with values tested to emailRegex
*/
let email: string;
let userInput: string;
// somehow get user input
if (emailRegex.test(userInput)) {
email = userInput;
} else {
console.log('User provided invalid email. Showing validation error');
// Some code for validation error
}
ãã®ææ¡ãå®è£ ãããšã次ã®ããã«ãªããŸãã
type Email = /.../;
let email: Email;
let userInput: string;
// somehow get user input
if (Email.test(userInput)) {
email = userInput;
} else {
console.log('User provided invalid email. Showing validation error');
// Some code for validation error
}
ã芧ã®ãšãããã³ãŒãã¯ã»ãšãã©åãã§ããããã¯ãæ£èŠè¡šçŸã®äžè¬çãªåçŽãªäœ¿çšæ³ã§ãã ãããã2çªç®ã®ã±ãŒã¹ã¯ã¯ããã«è¡šçŸåããããæ£èŠè¡šçŸã§æ€èšŒãããããšãæå³ããå€æ°ã«å²ãåœãŠãåã«æååããã§ãã¯ããã®ãå¿ãããªã©ããŠãŒã¶ãŒã誀ã£ãŠééããã®ãé²ããŸãã
2ã€ç®ã¯ããã®ãããªåã®çµã蟌ã¿ããªããšãéåžžãã€ã³ããã¯ã¹ã§æ£èŠè¡šçŸã§æ€èšŒãããåã䜿çšã§ããªãããšã§ããã»ãšãã©ã®å Žåããã®ãããªã€ã³ããã¯ã¹ãã£ãŒã«ãã¯ããªãã©ã«ã§å®è¡ã§ããããã«å®è¡æã«ãã§ãã¯ã§ããªãå€æ°ã§æ©èœããããã§ãã ã
@alexanderbird ããã®ã³ãŒããæå¹ã«ããããå®è¡æãšã³ã³ãã€ã«æã®äž¡æ¹ã§é衚瀺ã®ãã§ãã¯ãè¿œå ãããããããšã¯ãå§ãããŸããã
function foo(bar: number) {
let baz: /prefix:\d+/ = 'prefix:' + number;
}
ãã®ã³ãŒãã¯ç§ã®ææ¡ã®ããã«ãšã©ãŒãã¹ããŒããå¿ èŠããããŸãã ãããããã¯ïŒ
function foo(bar: number) {
let baz: /prefix:\d+/ = ('prefix:' + number) as /prefix:\d+/;
}
ãŸãã¯ããïŒ
function foo(bar: number) {
let baz: /prefix:\d+/;
let possibleBaz: string = 'prefix:' + number;
if (/prefix:\d+/.test(possibleBaz)) {
baz = possibleBaz;
}
}
æ£ããã§ãããããæŸåºãããã³ãŒãã«ã圱é¿ãäžããŸããã
ãŸããåã®ã³ã¡ã³ãã§ç€ºããããã«ããŠãŒã¶ãŒå ¥åããã®ä»ã®ãœãŒã¹ããã®åºãå·ãåŠçããªããã°ãªããªãããšãå€ããããäžè¬çãªãŠãŒã¹ã±ãŒã¹ã§ããªãã©ã«ã§ã¯ééããªãååã§ã¯ãããŸããã ãã®æŸåºã®åœ±é¿ãå®è£ ããªããšããŠãŒã¶ãŒã¯æ¬¡ã®æ¹æ³ã§ãã®ã¿ã€ããæäœããå¿ èŠããããŸãã
export type Email = /.../;
export const Email = /.../;
let email: Email;
let userInput: string;
// somehow get user input
if (Email.test(userInput)) {
email = <Email>userInput;
} else {
console.log('User provided invalid email. Showing validation error');
// Some code for validation error
}
ãŸãã¯äº€å·®ç¹ã®å ŽåïŒ
export type Email = /email-regex/;
export const Email = /email-regex/;
export type Gmail = Email & /gmail-regex/;
export const Gmail = {
test: (input: string) => Email.test(input) && /gmail-regex/.test(input)
};
let gmail: Gmail;
let userInput: string;
// somehow get user input
if (Gmail.test(userInput)) {
gmail = <Gmail>userInput;
} else {
console.log('User provided invalid gmail. Showing validation error');
// Some code for validation error
}
ã³ã³ãã€ã©ã§ç°¡åã«åŠçã§ããã®ã«ããŠãŒã¶ãŒã«ã³ãŒãã®è€è£œãšæ瀺çãªãã£ã¹ãã®äœ¿çšã匷å¶ããã®ã¯è¯ãæ¹æ³ã§ã¯ãªããšæããŸãã ãšãããã®åœ±é¿ã¯éåžžã«å°ãããäºæž¬å¯èœã§ãããŠãŒã¶ãŒãé©ãããããæ©èœã®èª€è§£ããã°ã®ç¹å®ãå°é£ã«ãªã£ããããããšã¯ãªããšç¢ºä¿¡ããŠããŸããããšãããã®å€æŽãªãã§ãã®æ©èœãå®è£ ããããšã¯ééããããŸããã
çµè«ãšããŠãç°¡åã«èšãã°ã regex-validated
åã¯ã¹ã³ãŒãå€æ°ãšã³ã³ãã€ã©åã®äž¡æ¹ã§ãããšèšãããã§ãã
@DanielRosenwasserãš@alexanderbirdããããŸããããã1ã€ã¢ã€ãã¢ããããŸãã ãã®ãããªæ§æã¯ã©ãã§ããïŒ
const type Email = /email-regex/;
ãã®å ŽåããŠãŒã¶ãŒã¯ãããtype
ãšconst
äž¡æ¹ãšããŠæ瀺çã«å®çŸ©ããå¿
èŠãããããããã®ãããªä¿®é£Ÿåã䜿çšããªãéããå®éã®åã·ã¹ãã ã«ã¯å€æŽããããŸããã ããããããã䜿çšããå Žåã§ãã次ã®å Žåãšåããšããããè¿œå ããããšã§ãã³ãŒãã®å€ãã®ééãããã£ã¹ããéè€ãåé¿ã§ããŸãã
const Email = /email-regex/;
ããã¯ãããããã®ãããªããšãå¯èœã«ããå¯èœæ§ãããããããã®ææ¡ã®åãªãæ¹åãããããã«å€§ããããã§ãïŒäŸã¯Reduxã䜿çšãããããžã§ã¯ãããã®ãã®ã§ãïŒïŒ
export type SOME_ACTION = 'SOME_ACTION';
export const SOME_ACTION = 'SOME_ACTION' as SOME_ACTION;
ã«å€æãããŠããŸã
export const type SOME_ACTION = 'SOME_ACTION';
ç§ã¯ããã€ãã®åæ§ã®ææ¡ãèŠã€ããããšããŸããããæåããŸããã§ããã ãããåé¿çã§ããå¯èœæ§ãããããã®ãããªã¢ã€ãã¢ãæ°ã«å ¥ã£ãå Žåã¯ãèšèšææ¡ãæºåããŠãã¹ãããããšãã§ããŸãã
@DanielRosenwasser ãããªãã®2çªç®ã®åé¡ã«ã€ããŠ-ç§ã®ææ¡ã§ã¯ã³ã³ãã€ã©ã¯ãªãã©ã«ã«å¯ŸããŠã®ã¿æ£èŠè¡šçŸãå®è¡ãã誰ãããã®ãããªããšãããããã«ã¯æãããªãã®ã§ãç§ã¯ãããèµ·ãããšã¯æããªãïŒ
let something: /some-regex-with-backreferences/ = `
long enough string to make regex.test significantly affect performance
`
ãšã«ããããªã¢ã«ã¿ã€ã ã®ããã©ãŒãã³ã¹ã«åœ±é¿ãäžããããã«ãªãã©ã«ã®é·ãããã¹ãããäžéšã®ãšãã£ã¿ãŒã·ããªãªã§ãã®ç¶æ³ã«çŽé¢ããŠãããšãã«ãŠãŒã¶ãŒã確èªã§ããªãå Žåã«ãŠãŒã¶ãŒã«èŠåãããã¥ãŒãªã¹ãã£ãã¯ãäœæã§ããŸããããŠãŒã¶ãŒãã³ã³ãã€ã«ãããšãã«ç¢ºèªããŸããäºæ¥ã ãŸãã¯ãä»ã®åé¿çãããå¯èœæ§ããããŸãã
3çªç®ã®è³ªåã«ã€ããŠã¯ããã¹ãŠãæ£ããç解ãããŠãããã©ããã¯ããããŸããããå®è£
ãç°ãªãå Žåã¯ã tsconfig
ããtarget
å¿ããŠæ£èŠè¡šçŸãšã³ãžã³ãéžæããå¿
èŠãããããã§ãã ããã«èª¿æ»ãå¿
èŠã§ãã
@DanielRosenwasseräœãèãã¯ãããŸããïŒ ðæåã®ææ¡ãšæåŸã®ææ¡ã«ã€ããŠã 2çªç®ã®æŠèŠããã£ãšè©³ãã説æããå¿ èŠããããããããŸãããã
@Igmatããªãã®ææ¡ã¯ãæ€èšŒãæåååã§ã®ã¿åœ¹ç«ã€ããã«å¶éããŠããŸãã @rylphsã®ææ¡ã«ã€ããŠã©ãæããŸããïŒ ããã«ããããã¹ãŠã®ããªããã£ãåã«å¯ŸããŠããäžè¬çãªæ€èšŒãå¯èœã«ãªããŸãã
type ColorLevel = (n:number) => n>0 && n<= 255
type RGB = {red:ColorLevel, green:ColorLevel, blue:ColorLevel};
let redColor:RGB = {red:255, green:0, blue:0} //OK
let wrongColor:RGB = {red:255, green:900, blue:0} //wrong
ãã ãããã®ã¡ã«ããºã ãããªããã£ããè¶
ããŠéããªããã£ãåã«æ¡åŒµããã®ã¯å€ããããšæããŸãã
1ã€ã®ãã€ã³ããšããŠã @ DanielRosenwasserãæèµ·ããåé¡ïŒããŸããŸãªæ£èŠè¡šçŸãšã³ãžã³ã®å®è£
ã«ã€ããŠïŒãæ¡å€§ãããŸã
@zspitzææã«èŠããŸãããé¢æ°ãã«ãŒã«ã«ãã£ãŠå¶éãããŠããããTSã«è€éãããåŒãå©çšã§ããªããªãœãŒã¹ã«äŸåããåŒãèšç®ããããããã³ã³ãã€ã©ã®ããã©ãŒãã³ã¹ã«å€§ããªåœ±é¿ãäžããå¯èœæ§ããããŸããã³ã³ãã€ã«æã«ã
@Igmat
æ©èœã¯ã«ãŒã«ã«ãã£ãŠå¶éãããŠããªããã
å ·äœçãªäŸãããã€ãèããŠããŸããïŒ ãããããæ€èšŒæ§æãTypescriptã®ãå®å šãªã/ã³ã³ãã€ã«æã®æ¢ç¥ã®ãµãã»ããã«å¶éããããšãå¯èœã§ãã
ãŠãŒã¶ãŒå®çŸ©åã¬ãŒãã«æ°ããåã
// type guard that introduces new nominal type int
function isInt(value: number): value is type int { return /^\d+$/.test(value.toString()); }
// -------------------------------------^^^^ add type keyword here
function printNum(value: number) { console.log(value); }
function printInt(value: int) { console.log(value); }
const num = 123;
printNum(num); // ok
printInt(num); // error
if (isInt(num)) {
printNum(num); // ok
printInt(num); // ok
}
@disjukrã¯èŠæ ããããŸãããåã®æ¡åŒµã«ã€ããŠã¯ã©ãã§ããããã
ãããã¯çµ¶å¯Ÿã«æ¡åŒµå¯èœã§ããå¿ èŠããããŸããïŒ ãããèŠæ±ããTypeScriptã®èšèšååã¯ãããŸããïŒ ããã§ãªãå Žåã¯ãæ¡åŒµå¯èœã§ã¯ãããŸãããã @ disjukrãææ¡ããåç®åãäœããªãããããããæã£ãŠãããš
æ¡åŒµæ§IMHOãååŸããã«ã¯ãããªãã¯ãªãšã€ãã£ããªãã®ãå¿ èŠã§ããããä»»æã®åã¬ãŒãïŒé¢æ°ïŒãå¥ã®ä»»æã®åã¬ãŒãã®ãµãã»ããã§ãããã©ãããå€æããããšã¯ã§ããŸããã
ã¿ã€ãã¢ãµãŒã·ã§ã³ã®èãæ¹ã䜿çšããŠãåºæ¬çãªãæ¡åŒµæ§ããåŸãããšãã§ããŸãïŒããããããªãã¯ãªãšã€ãã£ãããªãã®ã ãšèšã£ãŠããã®ã§ã¯ãããŸããã誰ããããªãã¯ãªãšã€ãã£ããªãã®ãæãä»ããŸã§ãããã«äžæçãªã®ã£ããããããšèšã£ãŠããŸãïŒã
function isInt(value: number): value is type int { return /^\d+$/.test(value.toString()); }
// assert that biggerInt extends int. No compiler or runtime check that it actually does extend.
function isBiggerInt(value: number): value is type biggerInt extends int { return /^\d{6,}$/.test(value.toString()); }
// -----------------------------------------------------------^^^^ type extension assertion
function printNum(value: number) { console.log(value); }
function printInt(value: int) { console.log(value); }
function printBiggerInt(value: biggerInt) {console.log(value); }
const num = 123;
printNum(num); // ok
printInt(num); // error
printBiggerInt(num); // error
if (isInt(num)) {
printNum(num); // ok
printInt(num); // ok
printBiggerInt(num); // error
}
if (isBiggerInt(num)) {
printNum(num); // ok
printInt(num); // ok
printBiggerInt(num); // ok
}
é³ãåºãªããŠã䟿å©ãããããŸããã ããããåé ã§è¿°ã¹ãããã«ãæ¡åŒµå¯èœã§ããå¿ èŠããããŸããããããšã@disjukrã§ææ¡ãããŠããããã«å®è£ ã§ããŸããïŒ ïŒåŸè ã®å Žåã¯ã @ disjukrã®æ¡åŒµäžå¯èœãªæ¹æ³ã§å®è£ ããããšããå§ãããŸããïŒ
äžçš®ã®ãªããããã¯ã @ DanielRosenwasserã®æåã®ã³ã¡ã³ãã«è¿ä¿¡ããŠ
ã«ã³ãåºåãã®ãªã¹ãã®å Žåã¯ã ^
$
ã¢ã³ã«ãŒãš/^((dog|cat|fish)(,|$))+$/
æåååãæ£èŠè¡šçŸ/#[0-9]{6}/
ããåãæ£èŠè¡šçŸ${TColor}
ãã¹ãã§ããããã«ããŸãã
type TColor = 'red' | 'blue' | /#[0-9]{6}/;
type TBorderValue = /[0-9]+px (solid|dashed) ${TColor}/
çµæïŒ
let border1: TBorderValue = '1px solid red'; // OK
let border2: TBorderValue = '1px solid yellow'; // TSError: .....
ãŠãŒã¹ã±ãŒã¹ïŒTypeScript typestyle
ãã¿ã€ãã»ãŒãããªCSSã¹ã¿ã€ã«ãäœæããããã®å°çšã©ã€ãã©ãªããããŸãã ã©ã€ãã©ãªã¯å®è¡æã«äœ¿çšãããã¡ãœãããå
¬éããå¿
èŠããããããäžèšã®ææ¡ãããæ©èœã¯éåžžã«åœ¹ç«ã¡ãŸããææ¡ãããæååæ£èŠè¡šçŸåã¯ã代ããã«ã³ã³ãã€ã«æã«ã³ãŒããåãã§ãã¯ã§ããéçºè
ã«åªããã€ã³ããªã»ã³ã¹ãæäŸããŸãã
@DanielRosenwasser @alexanderbird @Igmat ïŒIMOãã®ææ¡ã¯ãTypeScriptãšWebéçºã«ãšã£ãŠ
æ¡åŒµæ§ãšã¿ã€ãã®æŸåºãä»ã®æ©èœã®éªéã«ãªããªãããã«ããããšã«åæããŸãã ãããã®åŽé¢ã«æ確ãªéçããªãå Žåã¯ãåŸã§ããããå®è£ ããŠãã ããã
æååã§ã¯ãªãUUIDåãæ¢ããŠããã®ã§ãããã«å°çããŸããããããã£ãŠããã®å Žåãæååãå®çŸ©ããæ£èŠè¡šçŸããããšäŸ¿å©ã§ãã+åã®æå¹æ§ã確èªããæ¹æ³ïŒEmail.testã®äŸïŒã圹ç«ã¡ãŸãã
@skbergamããäžåºŠèªåã§å®è£ ããããšããŠããŸãã ããããTSãããžã§ã¯ãã¯æ¬åœã«å·šå€§ã§ãç§ãä»äºãããŠããã®ã§ãã»ãšãã©é²å±ããããŸããïŒç§ã¯ãã®æ°æ©èœã®ãã¹ããäœæããããšããã§ããŸããã§ããïŒã 誰ããTSã®æ¡åŒµã«ã€ããŠããå€ãã®çµéšãæã£ãŠãããªããã©ããªå©ãã倧ãã«ãããããã§ã...
èå³æ·±ãããšã«ãããã«ããåç®åãå¹æçã«äœæãããŸããããã¯ã2ã€ã®åäžã§ãªãæ£èŠè¡šçŸã®éã«ãµãã¿ã€ã/å²ãåœãŠå¯èœæ§ã®é¢ä¿ã確ç«ã§ããªãããã§ãã
@RyanCavanaugh以åã®@maiermicãã³ã¡ã³ãããŸãã
ç·šéïŒãã®åé¡ã¯å€é åŒæéã§è§£æ±ºã§ããããã§ãïŒæ£èŠè¡šçŸã®å å«åé¡ãåç §ïŒã
ããããããã¯ååã§ã¯ãªããããããŸãããïŒ å€ãã®æ£èŠè¡šçŸé¢ä¿ããªãããšã確ãã«æãã§ããŸãããããªãã¯æ±ºããŠç¥ããŸããã
åãã§ãã¯ã«é¢ããŠãæ£èŠè¡šçŸãè€è£œããã®ã奜ãã§ã¯ãªãã typeof
constãååã§ãªãå ŽåïŒ.d.tsãã¡ã€ã«ãªã©ïŒãTSã¯valueof e
ã«ã€ããŠã©ã®ããã«æããŸããïŒ e
ããªãã©ã«ã§ããå Žåã e
ã®ãªãã©ã«å€ããã以å€ã®å Žåã¯ãšã©ãŒïŒããã³ã undefined
ãããªãã®ãåºåããŸãïŒïŒ
@maxlkããããããã¯ããå€ããŠããŸãããæ£èŠè¡šçŸãååŸããŠããã以å€ã®å Žåã¯æå¹ãªå
¥åã®æ«å°Ÿã®ã³ã³ããšäžèŽããªãããã«æ¹åããŸããïŒãã¹ãhttps://regex101.com/r/AuyP3g/1ã§/^((dog|cat|fish)(,(?=\b)|$))+$/
ã ããã¯ãã³ã³ãã®åŸã®åèªæåã«æ£ã®å
èªã¿ã䜿çšããDRYã®æ¹æ³ã§åæ€èšŒããåã«åŒ·å¶ããŸãã
ããïŒ
ããã®ç¶æ³ã¯ã©ãã§ããïŒ
è¿ãå°æ¥ããã®æ©èœãè¿œå ããŸããïŒ ããŒããããã§ããã«ã€ããŠäœãèŠã€ãããŸããã
@lgmat lib.d.ts
䜿çšå¯èœãªå®çŸ©ã®ã¿ã䜿çšããŠãæ§æã1è¡ã®ç¢å°é¢æ°ã«å¶éããã®ã¯ã©ãã§ããïŒ
ãããã®çŽ æŽãããæ¹åã¯å©çšã§ããŸããïŒ å€åå°ãªããšãã¢ã«ãã¡ãªãªãŒã¹ã§ã¯ïŒ
æ£èŠè¡šçŸã§æ€èšŒãããåã¯ãã¹ãã®äœæã«æé©ã§ãããããŒãã³ãŒããããå ¥åã®æ€èšŒã¯åªããŠããŸãã
+1ã ç§ãã¡ã®ãŠãŒã¹ã±ãŒã¹ã¯éåžžã«äžè¬çã§ããããdd / mm / YYYYãã®ãããªæååã®æ¥ä»åœ¢åŒãå¿ èŠã§ãã
ææ¡ãããŠããããã«ãããã¯éåžžã«ã¯ãŒã«ãªæ©èœã§ãããå¯èœæ§ã¯ãããŸããã
ããè¯ãæ¹æ³ã¯ãïŒ21861ã§ææ¡ãããŠããããã«ã解æãã¢ãŠããœãŒã·ã³ã°ããŠãã©ã°ã€ã³ã«åºåããããšã§ãããã®æ¹æ³ã§ã¯ãåŠç¿æ²ç·ãæ¥ã«ãªããšãã代åãæã£ãŠãäžèšã®ãã¹ãŠãåé¡ã«ãªãããšã¯ãããŸããããã¡ãã£ãšïŒ ãã®äžã«æ£èŠè¡šçŸãã§ãã¯ãå®è£ ã§ãããããå ã®ææ¡ã¯åŒãç¶ãæå¹ã§ãããããé«åºŠãªæ©æ¢°ã«ãã£ãŠææ¡ãããŸãã
ã ããç§ãèšã£ãããã«ãããäžè¬çãªæ¹æ³ã¯ã©ããªãªãã©ã«ã®ããã®ã«ã¹ã¿ã æ§æãããã€ããŒã§ãããïŒïŒ21861
äŸïŒ
const uri: via URIParserAndEmitter = http://google.com;
console.log(uri); // --> { protocol: 'http', host: 'google.com', path: undefined, query: undefined, hash: undefined }
const a: via PositiveNumberParser = 10; // --> 10
const b: via PositiveNumberParser = -10; // --> error
const date: via DateParser = 1/1/2019; // --> new Date(2019, 1, 1)
@lgmat
lib.d.ts
䜿çšå¯èœãªå®çŸ©ã®ã¿ã䜿çšããŠãæ§æã1è¡ã®ç¢å°é¢æ°ã«å¶éããã®ã¯ã©ãã§ããïŒ
@zspitzã¯ãå€ãã®äººãäžå¹žã«ããã§ãããã圌ããèŠãããã«ãããã¯å¯èœã§ãããåºæ¬çã«åœŒãã®å®å šã®ããã«åœŒãã®ããã«çŠããããŠããŸãã
ãããã®çŽ æŽãããæ¹åã¯å©çšã§ããŸããïŒ å€åå°ãªããšãã¢ã«ãã¡ãªãªãŒã¹ã§ã¯ïŒ
ç§ã®ç¥ãéããããã«ã¯ãŸã ææ¡ãå¿ èŠã§ãã @ gtamas ã @ AndrewEastwood
ãŸããïŒ11152ãããã«åœ±é¿ãäžããŠãããšæããŸãã
@Igmatããªãã®ææ¡ã¯ãæ€èšŒãæåååã§ã®ã¿åœ¹ç«ã€ããã«å¶éããŠããŸãã @rylphsã®ææ¡ã«ã€ããŠã©ãæããŸããïŒ ããã«ããããã¹ãŠã®ããªããã£ãåã«å¯ŸããŠããäžè¬çãªæ€èšŒãå¯èœã«ãªããŸãã
type ColorLevel = (n:number) => n>0 && n<= 255 type RGB = {red:ColorLevel, green:ColorLevel, blue:ColorLevel}; let redColor:RGB = {red:255, green:0, blue:0} //OK let wrongColor:RGB = {red:255, green:900, blue:0} //wrong
ãã ãããã®ã¡ã«ããºã ãããªããã£ããè¶ ããŠéããªããã£ãåã«æ¡åŒµããã®ã¯å€ããããšæããŸãã
ããã§ç§ãç®ã«ããäž»ãªåé¡ã¯ãã»ãã¥ãªãã£äžã®æžå¿µã§ããæªæã®ããã³ãŒããæ³åããŠã¿ãŠãã ããããããã¡ã䜿çšããŠãã¿ã€ãããã§ãã¯ããªãããŠãŒã¶ãŒã®ã¡ã¢ãªãååŸããŸãã ãã®åšãã«å€ãã®ãµã³ãããã¯ã¹ãå®è£ ããå¿ èŠããããŸãã ç§ã¯ããã2ã€ã®ç°ãªã解決çãèŠãããšæããŸãã1ã€ã¯æååçšã§ããã1ã€ã¯æ°åçšã§ãã
ãããæªæãæã£ãŠäœ¿çšã§ããå¯äžã®æ¹æ³ã¯ãããã¯ãã©ãã¯åŒãäœæããããšã§ãããããRegExpã¯äžéšã®æ¡åŒµæ©èœã®åœ±é¿ãåããŸããã ããã¯èšã£ãŠããäžéšã®ãŠãŒã¶ãŒã¯æå³ããã«ãããè¡ãå¯èœæ§ããããããäœããã®ä¿è·ãå¿ èŠã§ãã ãããããæè¯ã®æ¹æ³ã¯ã¿ã€ããŒã ãšæããŸãã
1ã€ã®ãã€ã³ããšããŠã @ DanielRosenwasserãæèµ·ããåé¡ïŒããŸããŸãªæ£èŠè¡šçŸãšã³ãžã³ã®å®è£ ã«ã€ããŠïŒãæ¡å€§ãããŸã
確ãã«ãããã¯æªãããšã§ãããã³ãŒãããŒã¹ã«å¿ èŠãªregExpã®ãææ°ã®ãéšåãæå®ããããšã§è§£æ±ºã§ããŸãã ããã©ã«ãã§ã¯ããã¹ãŠã®ããŒãã§æ©èœããéåžžã®ïŒES3ã§ããïŒïŒæ£èŠè¡šçŸã«ãªã
const unicodeMatcher = /\u{1d306}/u;
let value: typeof unicodeMatcher;
function(input: string) {
value = input; // Invalid
if (input.match(unicodeMatcher)) {
value = input; // OK
}
}
ãŠãŒã¶ãŒãé«åºŠãªãã©ã°ã§ãã©ã°ãç¡å¹ã«ããå Žåã
let value: typeof unicodeMatcher = 'ð'; // Warning, string literal isn't checked, because `variable` is of type `/\u{1d306}/u`.
TypeScriptã¯ãæ瀺ããªãéããé«åºŠãªæ£èŠè¡šçŸãè©äŸ¡ããŸããã ããããäœãèµ·ãã£ãŠããã®ããé«åºŠãªæ£èŠè¡šçŸãã§ãã¯ãæå¹ã«ããæ¹æ³ã説æããŠãèŠåãåºãå¿ èŠãããããšããå§ãããŸãã
ãŠãŒã¶ãŒãé«åºŠãªãã©ã°ã§ãã©ã°ãæå¹ã«ããŠããŠãããŒããããããµããŒãããŠããå Žåã
let value: typeof unicodeMatcher = 'ð'; // OK
ãŠãŒã¶ãŒãé«åºŠãªãã©ã°ã§ãã©ã°ãæå¹ã«ããŠããŠãããŒããããããµããŒãããŠããå Žåã
let value: typeof unicodeMatcher = 'ð';
// Error, NodeJS does not support advanced RegExp, upgrade NodeJS to version X.Y.Z, or disable advanced RegExp checking.
ããã¯ãããåé¿ããããã®åççãªæ¹æ³ã ãšæããŸãã
ããã°ã©ããŒã®ããŒã ã¯éåžžãåãããŒãžã§ã³ã®NodeJSã䜿çšããŠãããããã¹ãŠã®ã³ãŒãããŒã¹ãæ°ããããŒãžã§ã³ã®ãŠãŒã¶ãŒã®ããã«æ©èœããŠãããããç°¡åã«ã¢ããã°ã¬ãŒãã§ããŸãã
ãœãããã°ã©ããŒã¯ãã®å Žã§ç°¡åã«é©å¿ã§ãã
ãã®åé¡ã®çŸåšã®ç¶æ³ã¯ã©ããªã£ãŠããŸããïŒ TypeScriptãããã»ã©å€§ããªå¯èœæ§ãç§ããäœåãã®çŽ æŽãããææ¡ãããŠããã®ãèŠãã®ã¯æ¬åœã«æ®å¿µã§ãããéçºè ããã¯ããŸã泚ç®ãããŠããŸããâŠ
å ã®ææ¡ã¯ã Emitã®æŠèŠãé€ãã°è¯ãã£ãã®ã§ãå®éã«ã¯å¿ èŠãªãã®ã§ãææ¡ã劚ããããšã¯ãããŸããã
察åŠããããšããŠããåé¡ã¯ãæ£èŠè¡šçŸãªãã©ã«ïŒæååããã³æ°å€ãªãã©ã«ãšå®è³ªçã«åçã§ããããé£ããããšã§ã¯ãããŸããïŒãšåæŒç®åpatternof
ïŒ typeof
ãšåæ§ïŒãå°å
¥ããããšã§è§£æ±ºã§ããŸãã keyof
ïŒãããã¯æ£èŠè¡šçŸãªãã©ã«åãåãã_validatedstring_åãè¿ããŸãã ããã¯ãããã©ã®ããã«äœ¿ãããããšãã§ãããã§ãïŒ
type letterExpression = /[a-zA-Z]/;
let exp: letterExpression;
exp = /[a-zA-Z]/; // works
exp = /[A-Za-z]/; // error, the expressions do not match
type letter = patternof letterExpression;
type letter = patternof /[a-zA-Z]/; // this is equivalent
let a: letter;
a = 'f'; // works
a = '0'; // error
const email = /some-long-email-regex/;
type email = patternof typeof email;
declare let str: string;
if (str.match(email)) {
str // typeof str === email
} else {
str // typeof str === string
}
@ m93aæåã®ææ¡ã«åãçµãã§ãããšããç§ã¯è¿œå ã®åæŒç®åã䜿çšãããã®ãããªè§£æ±ºçã«ã€ããŠèããŠããŸããã§ããã
ããã¯ããåé·ã«èŠããŸãããã¿ã€ãã«ãã£ãŠåŒãèµ·ããããæŸåºã®åœ±é¿ãåãé€ããã®ã¢ãããŒãã奜ãã§ãã
ãããŠããã¯ãïŒããªããææ¡ããããã«ïŒæ°ããããŒã¯ãŒãã®è¿œå ãã¹ãããããããã«ãã®ææ¡ãæ¡åŒµããæ¹æ³ãç§ã«å°ããŸãã-IMOã¯ãã§ã«ããªãã®éãæã£ãŠãããåã·ã¹ãã ããã®åœ±é¿ãæŸåºããŠããŸããïŒç§ã®ææ¡ã®ããã«ïŒã
4ã€ã®ã¹ããããå¿ èŠã§ãã
regexp-validated string literal
ã¿ã€ããè¿œå ããŸããTypeScript
type Email = /some-long-email-regex/;
RegExp
ã€ã³ã¿ãŒãã§ã€ã¹ããžã§ããªãã¯ã«å€æŽããŸãããïŒTypeScript
interface RegExp<T extends string = string> {
test(stringToTest: string): stringToTest is T;
}
TypeScript
const Email = /some-long-email-regex/; // infers to `RegExp</some-long-email-regex/>`
InstanceType
ãããªconditional types
æ©èœã䜿çšããŠã¿ã€ããã«ããŒãè¿œå ããŸããTypeScript
type ValidatedStringType<T extends RegExp> = T extends RegExp<infer V>
? V
: string;
䜿çšäŸïŒ
const Email = /some-long-email-regex/;
type Email = ValidatedStringType<typeof Email>;
const email: Email = `[email protected]`; // correct
const email2: Email = `emexample.com`; // compile time error
let userInput: string;
if (Email.test(userInput)) {
// `userInput` here IS of type `Email`
} else {
// and here it is just `string`
}
@Igmatã¯ãŒã«ã ããªãã®ææ¡ã¯TypeScriptã«ãšã£ãŠããèªç¶ã«æããããã³ã³ãã€ã©ãžã®å€æŽãå°ãªããŠæžã¿ãŸããããã¯ããããè¯ãããšã§ãã ç§ã®ææ¡ã®å¯äžã®å©ç¹ã¯ãæ£èŠè¡šçŸãªãã©ã«ãæååããã³æ°å€ãªãã©ã«ãšåãããã«æããããããšã§ãããããã¯ãäžéšã®äººã«ãšã£ãŠæ··ä¹±ãæãå¯èœæ§ããããŸãã
let a: 'foo' = 'foo'; // works
let b: 42 = 42; // works
let c: /x/ = /x/; // error
ããããç§ã¯ããªãã®ææ¡ã®åçŽããäžã€ã®æ¬ ç¹ãäžåã£ãŠãããšæããŸãã
ç·šéïŒ ValidatedStringType<R>
ã®é·ãã¯ããŸã奜ãã§ã¯ãããŸããã æ€èšŒæžã¿ã®æååãã¿ãŒã³ãåŒã³åºãããšã«ããå Žåãçµå±PatternOf<R>
䜿çšã§ããŸãã ããªãã®ã¿ã€ããã¿ã€ãããã®ã«ãã£ãšæéãããããšèšã£ãŠããã®ã§ã¯ãããŸãããã»ãšãã©ã®äººã¯æåã®3æåãã¿ã€ãããŠã¿ããæŒãã ãã§ãã ã³ãŒãã®spagetificationãžã®åœ±é¿ã倧ãããªããŸãã
@Igmatããªãã®ãœãªã¥ãŒã·ã§ã³ã¯éçºã®èŠ³ç¹ããã¯åªããŠããŸãããèªã¿ããããå¢ãã«ã€ããŠã
@Akxeéçºè ã1ã€ã®éåžžã«ç¹æ®ãªãŠãŒã¹ã±ãŒã¹ãããªãå¥ã®ããŒã¯ãŒããè¿œå ããããšã¯æããªãã
@RyanCavanaughããã«ã€ããŠã®ãæèŠããèãããã ããã ïŒå ·äœçã«ã¯ãå ã®ææ¡ãšæåŸã®4ã€ã®ã³ã¡ã³ãïŒãããé€ãïŒïŒããããšãããããŸãïŒ ïŒ+1ïŒ
ããã©ã«ãã§.*
èšå®ãããŠããæååã®ãžã§ããªãã¯åŒæ°ã䜿çšããã®
let a: 'foo' = 'foo'; // works
let b: 42 = 42; // works
let c: /x/ = /x/; // works
let d: string<x.> = 'xa'; // works
æååãªãã©ã«'foo'
ã¯string<foo>
ç ç³ãšèŠãªãããšãã§ããŸã
ValidatedStringType<R>
ã®é·ãã¯ããŸã奜ãã§ã¯ãããŸããã æ€èšŒæžã¿ã®æååã_patterns_ãšåŒã¶ããšã«ããå Žåãçµå±PatternOf<R>
䜿çšã§ããŸãã
@ m93a ãIMOããã®å Žåãæ¢åã®InstanceType
ããã³ReturnType
ãã«ããŒãšäžè²«æ§ãä¿ã€ããã«ãããããPatternType<R>
ãšåŒã¶æ¹ãããã§ãããã
@ amir-aradããããããã ãã®å Žåã interface RegExp
ã©ã®ããã«ãªããŸããïŒ
@RyanCavanaughå©ãã«ãªãã°ãæ°ããèŠã€ããæ¹æ³ã§å ã®ææ¡ãæžãçŽãããšãã§ããŸãã ããã¹ããïŒ
@ amir-aradææ¡ãããæ§æãä»ã®TypeScriptãšç«¶åããŠããŸãã ããã§ãåããžã§ããªãã¯åŒæ°ãšããŠã®ã¿æž¡ãããšãã§ããä»»æã®åŒãæž¡ãããšã¯ã§ããŸããã ææ¡ãããæ§æã¯éåžžã«æ··ä¹±ããŸãã
ãžã§ããªãã¯åã¯ãåãåããåãè¿ãé¢æ°ã®ããã«èããŠãã ããã 次ã®2ã€ã®ã³ãŒãã¯ãæå³ãšæ§æã®äž¡æ¹ã§éåžžã«è¿ããã®ã§ãã
function foo(str: string) {
return str === 'bar' ? true : false
}
type foo<T extends string> = T extends 'bar' ? true : false;
æ°ããæ§æã¯ãJavaScriptã®æ£èŠè¡šçŸãlet all = String(.*)
ãšæžãããšãææ¡ãããããªãã®ã§ããããã¯ãé¢æ°åŒã³åºãæ§æã®éãä¹±çšã«ãªããŸãã ãããã£ãŠãããªãã®ææ¡ã¯ããŸãæå³ããªããšæããŸãã
@ m93aç§ã®ææ¡ã¯ãJavaScriptã§ã¯ãªããåã®æ³šéã«é¢ãããã®ã§ããã
é ã®ãŠã£ãºãããã§ããïŒ
interface RegExp {
test(stringToTest: string): stringToTest is string<this>;
}
@ amir-aradãç³ãèš³ãããŸããããããªãã®ææ¡ã«ãã以äžäŸ¡å€ã®ãã詳现ãè¿œå ããããšã¯ã§ããŸãããã string
ã¯éåžžã«åºæ¬çãªããªããã£ãã§ãããããäžèŠãããšTSã³ã³ãã€ã©å
šäœã«éåžžã«éèŠãªå€æŽãå ããããããã«èŠããŸãã
æãããªåé¡ã¯èŠåœãããŸãããããã®ãããªææ¡ã¯ãã£ãšè©³çŽ°ã§ãå€ãã®æ¢åã®ã·ããªãªã«å ããŠããã®ç®çã®é©åãªæ£åœåãã«ããŒããå¿
èŠããããšæããŸãã
ããªãã®ææ¡ã¯1ã€ã®åãè¿œå ãã1ã€ã®ããªããã£ãåãå€æŽããŸãããç§ã®ææ¡ã¯1ã€ã®åã®ã¿ãè¿œå ããŸãã
æ®å¿µãªãããç§ã¯ãã®ãããªæ©èœã®ææ¡ãäœæããããã«å€ãã®æéãå²ãæºåãã§ããŠããŸããïŒãŸããTSã®ãã¹ãŠã®ææ¡ãå€§å¹ ãªé 延ãªãã«å®è£ ãããŠããããã§ã¯ãªãããšã«æ°ä»ããããããŸããïŒããããã«åãçµããªããç§ã¯å¿ èŠã«å¿ããŠãç§ã®ãã£ãŒãããã¯ãåãã§æäŸããŸãã
ãããã®æ£èŠè¡šçŸãå®éã®æ£èŠè¡šçŸïŒæ£èŠã§ã¯ãªãPerlã®ãããªæ£èŠè¡šçŸã§ã¯ãªãïŒã§ããå Žåããããã決å®æ§FSMã«å€æãããããã«çŽç©éåã䜿çšããŠãã¹ãŠã®æ¥ç¶è©ãšè«çåãååŸã§ããŸãã æ£èŠè¡šçŸã¯ããŒã«æŒç®ã§éããããŸãã
ãŸããæååãªãã©ã«åãã¢ãããã¯ã§ã¯ãªããã³ã³ãã€ã«æã®æåãªã¹ããšããŠè¡šãããŠããå Žåã¯ãã©ã€ãã©ãªã«ãã¹ãŠã®æŒç®åãå®è£ ã§ããŸãã ããã¯ããã©ãŒãã³ã¹ãå°ãæªåãããã ãã§ãã
ç·šéïŒééããä¿®æ£ããŸãã
ãã¹ãªã«ãå®éã«ãããã䜿çšã§ããããšã«
oninit
ã oncreate
ã onbeforeupdate
ã onupdate
ã onbeforeremove
ãããã³onremove
ã«ã¯ãç¬èªã®ããã¯ããããŸãç¹å¥ãªãããã¿ã€ããon
ã§å§ãŸããã®ã§ãããã€ãã³ããªã¹ããŒé¢æ°ãšã€ãã³ããªã¹ããŒãªããžã§ã¯ãïŒ handleEvent
ã¡ãœããã䜿çšïŒã®äž¡æ¹ããµããŒããã addEventListener
ãšremoveEventListener
ããããã£ãŠãæ£èŠè¡šçŸã§æ€èšŒãããæååå+åã®åŠå®ã䜿çšãããšãDOMvnodeã«å¯ŸããŠæ¬¡ã®ããšãã§ããŸãã
interface BaseAttributes {
// Lifecycle attributes
oninit(vnode: Vnode<this, Vnode<Attributes, []>>): void;
oncreate(vnode: Vnode<this, Vnode<Attributes, []>>): void;
onbeforeupdate(
vnode: Vnode<this, Vnode<Attributes, []>>,
old: Vnode<this, Vnode<Attributes, []>>
): void;
onupdate(vnode: Vnode<this, Vnode<Attributes, []>>): void;
onbeforeremove(vnode: Vnode<this, Vnode<Attributes, []>>): void | Promise<void>;
onremove(vnode: Vnode<this, Vnode<Attributes, []>>): void;
// Control attributes
key: PropertyKey;
}
interface DOMAttributes extends BaseAttributes {
// Event handlers
[key: /^on/ & not keyof BaseAttributes]: (
((this: Element, ev: Event) => void | boolean) |
{handleEvent(ev: Event): void}
);
// Other attributes
[key: keyof HTMLElement & not keyof BaseAttributes & not /^on/]: any;
[key: string & not keyof BaseAttributes & not /^on/]: string;
}
interface ComponentAttributes extends BaseAttributes {
// Nothing else interesting unless components define them.
}
ïŒãã®ãããªæ£èŠè¡šçŸããã°ã«ãŒããæœåºã§ããã®ãè¯ãããšã§ãããç§ã¯ããã«æ¯ãæ¢ããã€ããã¯ãããŸãããïŒ
ç·šéïŒææ¡ã®ããã€ãã®éèŠãªè©³çŽ°ãæ確ã«ããŸãã
ç·šé2ïŒå®éã«æ°åŠçã«æ£ç¢ºã«ãªãããã«ãã¯ãã«ã«ããããä¿®æ£ããŸãã
ç·šé3ïŒåäžæåã®å
±çšäœã®äžè¬çãªäž»æŒã®ãµããŒããè¿œå
ãããã¯ããã«å®çŸå¯èœã«è§£æ±ºããããšããå ·äœçãªææ¡ã¯æ¬¡ã®ãšããã§ãããã³ãã¬ãŒããªãã©ã«åã
ãŸããä»ã®ã¿ã€ããšããŒãžããã®ã¯ããªãç°¡åãªã¯ããªã®ã§ãå®å šãªæ£èŠè¡šçŸã¯ããããè¯ãèãã§ã¯ãªããšæããŸãã ãã¶ãããã¯ãã£ãšè¯ããããããŸããïŒãã³ãã¬ãŒããªãã©ã«ã¿ã€ãã
`value`
-ããã¯æåéã"value"
ãšåçã§ã`value${"a" | "b"}`
-ããã¯æåéã"valuea" | "valueb"
ãšåçã§ã`value${string}`
-ããã¯æ©èœçã«æ£èŠè¡šçŸ/^value/
ãšåçã§ããã "value"
ã "valuea"
ãããã³"valueakjsfbf aflksfief fskdf d"
ã¯ãã¹ãŠå²ãåœãŠå¯èœã§ãã`foo${string}bar`
-ããã¯æ©èœçã«ã¯æ£èŠè¡šçŸ/^foo.*bar$/
ãšåçã§ãããæ£èŠåãå°ãç°¡åã§ãã`foo${string}bar${string}baz`
ã¯ãæå¹ãªãã³ãã¬ãŒããªãã©ã«ã¿ã€ãã§ããstring
æ¡åŒµããå¿
èŠããããååž°çã§ãã£ãŠA
ã¯ã A
å²ãåœãŠå¯èœãªæååã®ã»ãããã B
å²ãåœãŠå¯èœãªæååã®ã»ããã®ãµãã»ããã§ããå Žåã«ã®ã¿ããã³ãã¬ãŒããªãã©ã«ã¿ã€ãB
å²ãåœãŠãããšãã§ããŸãã B
ãäžèšã«å ããŠãç¹å¥ãªstarof T
åãååšãã T
ã¯1æåã®æååãªãã©ã«åã®ã¿ã§æ§æãããŠããå¿
èŠããããŸãã string
ã¯ã starof (...)
åãšã€ãªã¢ã¹ãšããŠååšããŸããããã§ã ...
ã¯ãU +0000ããU + FFFFãŸã§ã®ãã¹ãŠã®åäžUCS-2æååãªãã©ã«ã®åéåã§ãïŒåç¬ãå«ãïŒã代çã ããã«ãããESã®åºæ°10ã®æ°å€ãªãã©ã«ã®å®å
šãªææ³ãå®çŸ©ã§ããŸãã次ã«äŸã瀺ããŸãã
type DecimalDigit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
type Decimal = `${DecimalDigit}{starof DecimalDigit}`
type Numeric = `${(
| Decimal
| `${Decimal}.${starof DecimalDigit}`
| `.${Decimal}`
)}${"" | (
| `E${Decimal}` | `E+${Decimal}` | `E-${Decimal}`
| `e${Decimal}` | `e+${Decimal}` | `e-${Decimal}`
)}`
åæ§ã«ãç¹å®ã®çµã¿èŸŒã¿ã¡ãœããã¯ããã®ãããªã¿ã€ããè¿ãããã«èª¿æŽã§ããŸãã
Number.prototype.toString(base?)
-ããã¯ãéçã«æ¢ç¥ã®base
ã«å¯ŸããŠãäžèšã®Numeric
ã¿ã€ããŸãã¯ãã®ããªã¢ã³ããè¿ãããšãã§ããŸãã+x
ã x | 0
ã parseInt(x)
ãªã©-äžèšã§å®çŸ©ããããã«x
ãNumeric
ããšãããã£ãŠããå Žåãçµæã®åã¯æ¬¡ã®ããã«ãªããŸãããªãã©ã«ã®æ°å€åãšããŠé©åã«æšæž¬ãããŸãããããŠæåŸã«ã次ã®ããã«äžèŽããã°ã«ãŒããæœåºã§ããŸãïŒ Key extends `on${infer EventName}` ? EventTypeMap[TagName][EventName] : never
ã ãã³ãã¬ãŒãæœåºã¯ãåžžã«ãã«ããŒã ã§æ©èœããããšãåæãšããŠãããããä»»æã®å
å«ãæ€çŽ¢ããã«ã¯ãæ瀺çã«${string}
è£éã䜿çšããå¿
èŠããããŸãã ããã¯æ¬²åŒµãã§ã¯ãªãã®ã§ã ` "foo.bar.baz" extends
$ {inferT}ã$ {infer U} ? [T, U] : never
ã¯["foo", "bar.baz"]
ã§ã¯ãªã["foo.bar", "baz"]
["foo", "bar.baz"]
è¿ããŸãã
æè¡çãªèŠ³ç¹ãããããã¯çã®æ£èŠè¡šçŸãããã¯ããã«å®è£ å¯èœã§ãã JSã®æ£èŠè¡šçŸã§ãå®æçã§ã¯ãããŸãã-圌ãã¯ç¶æ³äŸååã®ããã¯åç §ãšãªãã圌ãã¯åæ§ã®åœ¢ã§å€ãã®è€éãæ£èŠèšèªãããããã1ã€ãåºç€ãšãªãçè«ãšéåžžã«å¯æ¥ã«äžèŽããŸãïŒãã ãããã®ãµãã»ããã®ã¿ããµããŒãããŸãïŒã
""
"a" | "b"
`${a}${b}`
starof T
ïŒ T
ã¯ãåäžã®æåãšå
±çšäœã®ã¿ãå«ããããšãã§ããŸããïŒããã«ãããæååã®ãµãã¿ã€ãããµãã°ã©ãåååé¡ã®ææªã®ã·ããªãªã®ãµãã»ããããã§ãã¯ããããã«ãªãå¯èœæ§ããããŸãããããã«ã¯ããã€ãã®å€§ããªåéèŠå ããããŸãã
ã¯ããã«äžè¬çãªã±ãŒã¹ã¯ãå°ããªæéã®æååã®çµåã§ããããã¯ãæšã§ã¢ãã«åã§ãããã®ã§ãã ããã¯æ¯èŒçæçœã§ãã ïŒäžèšã®ãããã³ã°ã¢ã«ãŽãªãºã ãè€éã«ãªããããããŒããšããŠçµåããããšã¯ãå§ãããŸããããåäžæåã®åéåãªã©ãåäžã®åå²+çµåã«æ£èŠåããããšã¯ãŸã£ããåé¡ãããŸãããïŒ
çµ±åã¿ã€ãå šäœãæåã°ã©ããšããŠã¢ãã«åã§ããŸããããã§ã
ç§ãç°¡åã«è¡ã£ããã®Math.SEãã£ããïŒã»ãŒããããéå§ïŒã«ãããšããã®çµæã®ã°ã©ãã«ã¯ãæçã®å±ïŒã€ãŸããä»ã®ãšããžãè¶
ãããžã£ã³ãã®æ°ãæé*ïŒãšã starof
ããªãããšã®äž¡æ¹ãããããšãããããŸããåã®å¹³çããããå€é
åŒæéã®åé¡ã«éå
ããããšãæå³åŒ·ãæããŸãã ïŒäžèšã®ãªã³ã¯å
ã®ãŠã£ãããã£ã¢ã®èšäºã«ã¯ããã¢ã«ãŽãªãºã ãã«ããã€ãã®äŸããããç¹å¥ãªå€§æåãšå°æåãé©çšãããå¯èœæ§ã®ããã»ã¯ã·ã§ã³ãåç
§ããŠããŸããïŒ
ãããã®ããŒã¯ã©ãã倧ãããªãå¯èœæ§ãäœããããããã§ã®å®éã®å®è¡æã³ã¹ãã®ã»ãšãã©ã¯ãå®éã«ã¯ä»ã®æ¹æ³ã§ååŽãããŸãã å°ããªããŒã«å¯ŸããŠé«éã§ããéããããã§ååã§ãã
æ¯èŒããããã¹ãŠã®ãµãã°ã©ãã¯ãå°ãªããšã1ã€ã®ããŒãïŒã«ãŒãããŒãïŒãå ±æããŸãã ïŒããã¯æååã®å§ãŸããè¡šããŸããïŒãããã£ãŠãããã¯ããèªäœã§åé¡ã¹ããŒã¹ãåçã«æžãããå€é åŒæéãã§ãã¯ãä¿èšŒããŸãã
ãã¡ããããã®ãããªã¿ã€ãã®äº€å·®ã¯éèŠã§ãããäžèšã®å¶éã®ããã«ãåæ§ã®åéèŠå ãååšããããã«æããŸãã ç¹ã«ãæåŸã®å¶éã«ãããæããã«å€é åŒæéã§å®è¡ã§ããŸãã
*æ°åŠçã«ã¯ãå±ã¯ããã°ã©ããŒã«ãšã£ãŠå°ãçŽæã«åããŠå®çŸ©ãããŸãïŒãžã£ã³ããªãã§ã°ã©ããæç»ããããã«ãµãŒãã§ã¹ã«çªãåºãå¿ èŠã®ããæå°ã®ç©Žã®æ°ïŒããå¶éãããå±ïŒéãããæ°ã®ç©ŽïŒã¯éãããæ°ã®ãžã£ã³ããæå³ããŸãã
ãã®å ·äœçãªææ¡ã䜿çšããŠããã®ã³ã¡ã³ãããã®ç§ã®äŸãã©ã®ããã«ç¿»èš³ããããã次ã«ç€ºããŸãã
// This would work as a *full* type implementation mod implementations of `HTMLTypeMap` +
// `HTMLEventMap`
type BaseAttributes = {
// Lifecycle attributes
oninit(vnode: Vnode<this, Vnode<Attributes, []>>): void;
oncreate(vnode: Vnode<this, Vnode<Attributes, []>>): void;
onbeforeupdate(
vnode: Vnode<this, Vnode<Attributes, []>>,
old: Vnode<this, Vnode<Attributes, []>>
): void;
onupdate(vnode: Vnode<this, Vnode<Attributes, []>>): void;
onbeforeremove(vnode: Vnode<this, Vnode<Attributes, []>>): void | Promise<void>;
onremove(vnode: Vnode<this, Vnode<Attributes, []>>): void;
// Control attributes
key: PropertyKey;
}
interface HTMLTypeMap {
// ...
}
interface HTMLEventMap {
// ...
}
// Just asserting a simple constraint
type _Assert<T extends true> = never;
type _Test0 = _Assert<
keyof HTMLTypeMap[keyof HTMLTypeMap] extends `on${string}` ? false : true
>;
type EventHandler<Event> =
((this: Element, ev: Event) => void | boolean) |
{handleEvent(ev: Event): void};
type Optional<T> = {[P in keyof T]?: T[P] | null | undefined | void}
type DOMAttributes<T extends keyof HTMLAttributeMap> = Optional<(
& BaseAttributes
& {[K in `on${keyof HTMLEventMap[T]}` & not keyof BaseAttributes]: EventHandler<(
K extends `on${infer E}` ? HTMLEventMap[E] : never
)>}
& Record<
keyof `on${string & not keyof HTMLEventMap}` & not keyof BaseAttributes,
EventHandler<Event>
>
& Pick<HTMLTypeMap[T], (
& keyof HTMLTypeMap[T]
& not `on${string}`
& not keyof BaseAttributes
)>
& Record<(
& string
& not keyof HTMLTypeMap[T]
& not keyof BaseAttributes
& not `on${string}`
), string | boolean>
)>;
ç·šéïŒããã«ãããLodashã®_.get
ã¡ãœãããšã _.property(path)
ã¡ãœããã_.map(coll, path)
ç瞮圢ãªã©ãããããã£ã®çç¥åœ¢ã䜿çšããé¢é£ã¡ãœããã®90ïŒ
ãæ£ããå
¥åããããšãã§ããŸãã ããããç§ãèããŠããªãä»ã®ããã€ãããããŸãããããã¯ããããç§ãèããããšãã§ããæ倧ã®ãã®ã§ãã ïŒãã®ã¿ã€ãã®å®è£
ã¯èªè
ã®ç·Žç¿åé¡ãšããŠæ®ããŠãããŸããããããšã {0: ..., 1: ...}[Path extends "" ? 0 : 1]
ãããªããã«ã€ã³ããã¯ã¹ä»ããããã¬ã³ãŒããæã€æ¡ä»¶ä»ãã¿ã€ãã®éåžžã®ããªãã¯ã®çµã¿åããã§å¯èœã§ããããšãä¿èšŒã§ããŸãã
ç§ã®æšå¥šäºé ã¯ãæ£èŠè¡šçŸã¿ã€ãã®å®è£ ã«äœ¿çšã§ããã¿ã€ããããã€ããŒã®å®è£ ã«æ³šåããããšã§ãã
æ£èŠè¡šçŸã¿ã€ããçŽæ¥å®è£ ããã®ã§ã¯ãªãããªããããã€ããŒãã¿ã€ãããã®ã§ããïŒ ãªããªã
FïŒã«ã¯ãªãŒãã³ãœãŒã¹ã®æ£èŠè¡šçŸã¿ã€ããããã€ããŒããããŸãã
ã¿ã€ããããã€ããŒã«é¢ããããã€ãã®æ å ±ïŒ https ïŒ
ã¿ã€ããããã€ããŒãå®è£ ãããæ£èŠè¡šçŸã¿ã€ããããã€ããŒããªãŒãã³ãœãŒã¹ã©ã€ãã©ãªãšããŠå®è£ ããããšã次ã®ããã«äœ¿çšããããšãæ³åã§ããŸãã
type PhoneNumber = RegexProvider</^\d{3}-\d{3}-\d{4}$/>
const acceptableNumber: PhoneNumber = "123-456-7890"; // no compiler error
const unacceptableNumber: PhoneNumber = "hello world"; // compiler error
@AlexLeungå°ãªããšããã®ãªã¯ãšã¹ãã«ã€ããŠã¯ããããæ£ããæ¹æ³ã§ãããšã¯ç¢ºä¿¡ããŠããŸããã
string
ãµãã¿ã€ãRegexProvider</^foo$/>
ãšåçã«æ±ãããããšã¯ãªã"foo"
ããããã®åç®äžã®ãµãã¿ã€ããã ããã«ã RegexProvider</^foo$/>
ãšRegexProvider</^fo{2}$/>
ã¯ã2ã€ã®ç°ãªãã¿ã€ããšããŠæ±ãããŸãããããã¯ç§ã奜ãã§ã¯ãªãããšã§ãã 代ããã«ãç§ã®ææ¡ã¯ãæååãã³ã¢ã«çŽæ¥çµ±åãã圢åŒèšèªèªèã®çè«ããçŽæ¥æ
å ±ãåŸãŠãèªç¶ã«åãŸãããã«ããŸããKey extends `on${infer K}` ? K : never
ãŸãã¯Key extends `${Prefix}${infer Rest}` ? Rest : never
ä»ããŠæååã®äžéšãæœåºããããšãã§ããŸãã ã¿ã€ããããã€ããŒã¯ãã®æ©èœãæäŸããŠãããããã®ãããªæ©èœãè¿œå ãããå Žåã«ã©ã®ããã«ãã¹ããæ確ãªæ¹æ³ã¯ãããŸããã/.*/
ã®ä»£ããã«ã string
èªäœãšçµ±åããããšãææ¡ããŸãã APIãå€æŽããå¿
èŠã¯ãªããã³ãŒãããŒã¹ã®æ®ãã®éšåããã»ãšãã©åãé¢ãããŠãã2ã€ã®çè«çã«è€éãªéšåãé€ãã°ããã³ãã¬ãŒããªãã©ã«åãå¥ã®åã«å²ãåœãŠå¯èœãã©ãããèšç®ããæååããã¹ã©ã€ã¹ãæœåºããããšã¯ãåçŽã§ã¯ãªãã«ããŠãåæ§ã§ãã ã å®è£
ããããšããã§ãç§ã®ææ¡ã¯ãŸã ãã®PhoneNumber
äŸãå
¥åããããšãã§ããŸãã ããå°ãåé·ã§ãããä»ã®å Žæã«ååšããããŒã¿ã§ã¯ãªãããã§ã«TSã©ã³ãã«ããããŒã¿ãã¢ãã«åããããšããŠããŸãïŒFïŒã®ã¿ã€ããããã€ããŒãæã圹ç«ã€ãã®ïŒã ïŒããã¯æè¡çã«ã¯ããã§å¯èœãªé»è©±çªå·ã®å®å
šãªãªã¹ãã«æ¡åŒµãããããšã«æ³šæãã䟡å€ããããŸããïŒ
type D = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
type PhoneNumber = `${D}${D}${D}-${D}${D}${D}-${D}${D}${D}${D}`;
RegexProvider ^ foo $ />ãšRegexProvider ^ fo {2} $ />ã¯ã2ã€ã®ç°ãªãã¿ã€ããšããŠæ±ãããŸã
åãããã€ããŒã¯ãããã€ãã®equals
ãŸãã¯compare
ã¡ãœããã®å®è£
ãå¿
èŠãšããå¯èœæ§ããããããæ£èŠè¡šçŸåãããã€ããŒã®åãããã€ããŒã®äœæè
ã¯ãäžèšã®äž¡æ¹ã®ã±ãŒã¹ãåçã®åã§ãããšå®çŸ©ã§ããŸãã åãããã€ããŒã®äœæè
ã¯ãæ§é åãŸãã¯å矩åã®åä»ããèªç±ã«å®è£
ã§ããŸãã
ãããããæååãªãã©ã«åãåãããã€ããŒãšããŠå®è£ ããããšãå¯èœã§ãããã æ§æãåãã§ããå¯èœæ§ã¯ãªããšæããŸãããå¯å€æ°ã®åŒæ°ãåãåãåãããã€ããŒã«è¿ã¥ãããšãã§ããŸãã
type D = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
type PhoneNumber = StringTemplateMatcherProvider<D, D, D, "-", D, D, D, "-", D, D, D, D>;
@AlexLeungããããã¿ã€ã"123-456-7890"
ã¯ããªãã®ã¿ã€ãã«å²ãåœãŠå¯èœã§ããïŒ ïŒãããããªããããã¯å®è£
ãè€éã«ãããã§ãã«ãŒãããªãé
ãããŸããïŒ
æå
ã®è°è«ã«åé¢é£ããŠãã¿ã€ããåºå®é·ïŒé»è©±çªå·ãªã©ïŒã§ãªãå Žåã¯ã©ããªããŸããïŒ æè¿ããã䜿çšããããšæã£ãç¶æ³ã®1ã€ã¯ã thread_{number}
圢åŒã®éšå±åãä¿åããå Žåã§ãã
ãã®ãããªå€ã«äžèŽããæ£èŠè¡šçŸã¯thread_[1-9]\d*
ã§ãã ææ¡ãããŠãããã®ã§ã¯ããã®ãããªãã©ãŒãããã«äžèŽãããããšã¯å®è¡å¯èœã§ã¯ãªãïŒãŸãã¯äžå¯èœã§ããããïŒããã«æãããŸãã ãã®ç¶æ³ã§ã¯ãå€ã®æ°å€éšåã¯ãŒããã倧ããä»»æã®é·ãã«ãªãå¯èœæ§ããããŸãã
@jhprattå°ãå€æŽããã ãã§ããã®ã§ãããã«å¯Ÿå¿ããããã«starof ("0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9")
â /^\d*$/
ã®åœ¢åŒã§ææ¡ãä¿®æ£ããŸããã string
ã/^[\u0000-\uFFFF]*$/
ãšåãããã«æé©åãããã®ã§ãå
ã«é²ãã§ãããäžè¬åããããšã«ããŸããã
èšç®ã®è€éãã®æžå¿µãããä»»æã®éååž°çåéåãåãå
¥ããããã«ã starof
ãã以äžæ¡åŒµããããããŸããã2ã€ã®ä»»æã®æ£èŠè¡šçŸ*ãç䟡ã§ãããã©ããã®æ€èšŒã¯ãå€é
åŒç©ºéãŸãã¯å€é
åŒæéã§å®è¡ã§ããŸãïŒäž¡æ¹ãæå°éã®DFAã«å€æããŠæ¯èŒããŸãïŒéåžžã®æ¹æ³ã§ãããå®éã«ã¯éåžžã«é
ãã§ãïŒããäž¡æ¹ã®æ¹æ³ã¯å®éã«ã¯a{2}
ïŒãåºæ¬çã«å®è¡äžå¯èœã§ãïŒææ°é¢æ°çãªè€éãïŒ ã ããã¯åçæ§ã®ããã ãã§ãããæ£èŠè¡šçŸãæååã®ãµãã»ãããšäžèŽãããã©ããã®ãã§ãã¯ã¯ãå²ãåœãŠå¯èœæ§ã®ãã§ãã¯ã«å¿
èŠãªãå¥ã®æ£èŠè¡šçŸãäžèŽããæååã®ãµãã»ãããšäžèŽãããã©ããã確èªããããšã¯æããã«ããã«è€éã«ãªããŸãã
*æ°åŠçãªæå³ã§ã®æ£èŠè¡šçŸïŒ ()
ã (ab)
ã (a|b)
ãããã³(a*)
åäžæåã®ã¿ãå«ããŸããããã§ã a
ãšb
ã¯ããã®ãªã¹ãã®åã¡ã³ããŒã§ãïŒç°ãªãå¯èœæ§ããããŸãïŒã
ããã¯ããããã°ããã質åã§ãã...ååã«å¶éãããŠããå Žåãæ€èšŒé¢æ°ïŒã©ã ããŸãã¯ååä»ãïŒããµããŒãããã®ãããªãç°¡åã§ã¯ãªãã®ã¯ãªãã§ããïŒ
ããšãã°ã次ã®èŠçŽ ãããªããŒã¿ãŒã§ããããšã瀺ãããã«ãïŒãã䜿çšãããšããŸãïŒããã«ã€ããŠæèŠãããå Žåã¯ããïŒãã®ä»£ããã«å¿ èŠãªãã®ã䜿çšããŠãã ããïŒã
type email = string : (s) => { return !!s.match(...) }
type phone_number = string : (n) => { return !!String(n).match(...) }
type excel_worksheet_name = string : (s) => { return (s != "History") && s.length <= 31 && ... }
æåã®ã¹ã¿ãŒããšããŠãtypescriptã¯æ¬¡ã®ãããªæ€èšŒé¢æ°ã®ã¿ãåãå ¥ããããšãã§ããŸããã
äžèšã®æ¡ä»¶ã¯ãtypescriptã³ã³ãã€ã©ã«ãšã£ãŠç°¡åã«ç¢ºèªã§ããããã«èŠããŸãããããã®æ¡ä»¶ãæ³å®ããããšãå®è£ ã®è€éãã®å€ãã¯è§£æ¶ãããŸãã
ããã«ãå¿ èŠã«å¿ããŠãåæã¹ã³ãŒãã管çå¯èœãªãµã€ãºã«å¶éããŸãã
ãã®æåŸã®å¶éã¯ããã»ã©å¿ èŠã§ã¯ãªããšæããŸããããããå¿ èŠãã©ããã«ã€ããŠçåãããå Žåã¯ãäžèšã®å¶éã®ãã解決çã§ãããããããã«ã€ããŠè°è«ããã®ã«å€ãã®æéãè²»ãã䟡å€ã¯ãªããšæããŸããããã§ããå®éã®ãŠãŒã¹ã±ãŒã¹ã®èšå€§ãªç¯å²ã解決ã§ããŸãã ããã«ãäžèšã®å¶éãåŸã§ç·©åãããšãåºæ¬çãªæ§æãå€æŽããå¿ èŠããªããã³ã³ãã€ã©ã«ããèšèªãµããŒãã®å¹ ãåºããã ãã®åçŽã§èªç¶ãªæ¡åŒµã«ãªããããäžèšã®å¶éã®æ¬ ç¹ã¯ã»ãšãã©ãããŸããã
@mewaligã€ãŸããã©ã³ã¿ã€ã é¢æ°ã®ããã«èŠãããã®ã¯ãå®éã«ã¯ã©ã³ã¿ã€ã ã§ã¯ãªããã³ã³ãã€ã«æïŒããã³çœ²åå¯èœæ§ããã§ãã¯ãããã³ïŒã«å®è¡ãããŸãã ãããã®é¢æ°ã¯ãã©ã³ã¿ã€ã ïŒå€æ°ãé¢æ°ïŒ
ããã«ãäžè¬çã«ãã³ã³ãã€ã©ã«ã¹ããŒãããã®ãç¹ã«æé©åãäžååãªé¢æ°ãå®å
šã«æªæã®ããwhile(true){}
ãå®è¡ãããããããŸããã ã¡ã¿ããã°ã©ãã³ã°ãå¿
èŠãªå Žåã¯ãã¹ããŒãã«èšèšããå¿
èŠããããŸãã å®è¡æã³ãŒããã³ã³ãã€ã«æã«ã©ã³ãã ã«å®è¡ã§ããããã«ããããšã¯ããããå®è¡ããããã®ãPHPã®æ¹æ³ãã§ãã
æåŸã«ãææ¡ããæ§æã¯éåžžã®ãã¿ãŒã³ãåãæ¿ããŸã
let runtime: types = runtime;
ïŒã€ãŸããã³ãã³ã®åŸã®ã¿ã€ãïŒè£è¿ããäºå®äž
type types = types: runtime;
ããã¯æãããã§ãã ã ããããªãã®ææ¡ã«æè¬ããŸãããããããã¯ééããªãæªãèãã§ãã
ãããã®é¢æ°ã¯ãã©ã³ã¿ã€ã ïŒå€æ°ãé¢æ°ïŒ
ã³ã³ãã€ã©ãããå Žåã¯ãã¡ããã圌ãã¯ãECMAScriptã®ã¯ããããå©çšå¯èœãªã©ã³ã¿ã€ã ãã§ãïŒ tsc
ãšããã§ããããŸããïŒïŒã ã³ã³ãã€ã«æã®ã»ãã³ãã£ã¯ã¹ãããšãã°fetch()
ãšå®è¡æã®ã»ãã³ãã£ã¯ã¹ã«ã¯æããã«ãããŸããªåé¡ããããŸããããããå埩ã®ç®çã§ãã
å®è¡æã³ãŒããã³ã³ãã€ã«æã«ã©ã³ãã ã«å®è¡ã§ããããã«ããããšã¯ããããå®è¡ããããã®ãPHPã®æ¹æ³ãã§ãã
ããã¯ã C ++ã®constexpr
é¢æ°ãšéåžžã«ãã䌌ãŠããŸãã 解決çã¯ã constexpr
ã¯constexpr
ãã䜿çšã§ããªããããã¹ãŠãconstexpr
䜿çšã§ãããšããããšã§ãã 次ã«ãã³ã³ãã€ã«æã®ãã¡ã€ã«ã·ã¹ãã çšã«constexpr
åçã®ããŒãžã§ã³ã®ãã¡ã€ã«ã·ã¹ãã ãäœæã§ããŸããããã¯éåžžã«åŒ·åã§ãã
æ§æãç§ã«ã¯å€§äœããŸãèŠããŸããLHSã¯ã¿ã€ãã§ããããã¡ããRHSãããçš®ã®ã¿ã€ãã§ãã ç§ã®åé¡ã¯ããããŒã¹ãã¿ã€ããè¶ ããŠã¿ã€ããæ§æããæ¹æ³ã«é¢ãããã®ã§ãããããããã¹ãŠè§£æ±ºå¯èœã§ãã
ã ããããªãã®ææ¡ã«æè¬ããŸãããããããã¯ééããªãæªãèãã§ãã
ããã¯æªãèãã«ãªã£ãŠããŸããããããŸããããä»ã®ãšããç§ã¯ãtypescriptã®ç®æšãã倧ããå€ããå¿ èŠããããšæãããéåžžã«ç¹å®ãããŠããªãèããèŠãŠããã ãã§ãã ããã«äŒŒãè¯ãã¢ã€ãã¢ããªããããããªããšããæå³ã§ã¯ãããŸããïŒ
ãã®æ©èœã«é¢ããè°è«ã¯ä»ã®ãšããæ¢ãŸã£ãŠããããã§ãïŒ PRã¯çµäºããŠããããã¶ã€ã³ããŒãããŒã ã«ãããšã_åç®åãšäžè¬åãããã€ã³ããã¯ã¹çœ²åãã§ãããŸã§ããã«ã³ãããããããªãã®ã§ãããããã©ã®ããã«èŠããããç¥ãå¿ èŠããããŸãã_ïŒã
ãšã«ãããæ£èŠè¡šçŸãã¿ãŒã³ã®æœåºããµããŒããããçŸåšã®PRã«å¯Ÿããå¥ã®ä»®æ³çãªæ¡åŒµãææ¡ããããšæããŸãïŒ @isiahmeadowsã¯åœŒèªèº«ã®ææ¡ãæ瀺ããŸããããæ£çŽãªãšãããä»ã¯é ãå ãããšãã§ããŸãã...ïŒã
ç§ã¯çŸåšã®PRãæ¬åœã«å¥œãã§ãããã«åºã¥ããŠææ¡ãããŸãã é¢æ°ïŒããã³infer
ããŒã¯ãŒããæã€æ¡ä»¶ä»ãåïŒã«å¯ŸããŠæã£ãŠãããžã§ããªãã¯ååŒæ°æšè«ã«åºã¥ããæ§æãææ¡ããããšæããŸãã 人ã
ããã§ã«ãžã§ããªãã¯é¢æ°ã§æž¡ããããªãã©ã«ãªããžã§ã¯ãããåããæœåºãã§ãããšããçŽæãæã£ãŠããããã§ãã
ããšãã°ããã®ã¿ã€ãããããŸãã
type Prop1 = /(\w)\.(\w)/
ãã®åã䜿çšããŠãªãã©ã«åããã¹ãã§ããŸã
const goodLiteral = "foo.bar";
const badLiteral = "foo";
const regextTest: Prop1 = goodLiteral; //no error
const regextTest: Prop1 = badLiteral; //compiler error
function funProp1(prop: Prop1) { }
funProp1(goodLiteral); //no error
funProp1(badLiteral); //error
ãã ããé¢æ°ãã©ã¡ãŒã¿ãŒã§æ£èŠè¡šçŸåã䜿çšããå Žåã¯ãå±±æ¬åŒ§æ§æã䜿çšããŠãäžèŽããæååãæšæž¬ããããšãæå³ã§ããŸãã äŸãã°
type Prop1 = /(\w)\.(\w)/
const Prop1 = /(\w)\.(\w)/
const goodLiteral = "foo.bar";
const badLiteral = "foo";
function funProp1<M1 extends string, M2 extends string>(prop: Prop1<M1, M2>) : [M1, M2]
{
const m = prop.match(Prop1);
return [m[1], m[2]];
}
const res1 = funProp1(goodLiteral); //no error. Function signature inferred to be funProp<"foo", "bar">(prop: Prop1<"foo", "bar">) : ["foo", "bar"]
const res2 = funProp1(badLiteral); //compiler error
res1
æšå®ã¿ã€ãã¯["foo", "bar"]
ããšã«æ³šæããŠãã ãã
ãã®ã³ãŒããæ©èœããããã«ãã¿ã€ãã»ãŒããªãæååãã¹ãã²ãã¿ãŒãå®è£ ã§ããŸãã
const deep = get(objNested, "nested.very.deep")
ããããããããããã¯è§£æ±ºããããã«å¿
èŠãšãªãããããæã
ã¯å¯èœæ§ã®åºå®æ倧æ°ã®ããã«å€ãã®éè² è·ãåé¿ãããå Žåã¯get
ã®ãæ·±ã"ã
ããšãã°ã httpsïŒ//github.com/Microsoft/TypeScript/issues/12754ã®ãããªããšãã§ãããšããã{ [ StripAsyncSuffix<P> for P in K ] : T[P] }
ãããªæ§æã誰ãããã§ã«ãã®ãããªãã®ãææ¡ããŠããŸãïŒ
ããããä»ã®ãŠãŒã¹ã±ãŒã¹ãããã§ãããã ããããç§ã¯ã»ãšãã©ããããã®2ã€ã®ã¿ã€ãã«åœãŠã¯ãŸããšæããŸãïŒ1.æäŸãããæååãªãã©ã«ã«åºã¥ããŠé©åãªã¿ã€ããèŠã€ãåºãã2ãå ¥åã¿ã€ãã®ããããã£åãæ°ããå®çŸ©ãããã¿ã€ãã®æ°ããããããã£åã«å€æããïŒ
ããã¯ç§ãã¡ãã§ããããšã§ãã
ç§ã¯çŸåšãURLãæ€èšŒã§ããããã«ããããã«ã«ã¹ã¿ã lintã«ãŒã«ãæ§ç¯ããŠããŸã-ãã ãããªãã·ã§ã³ã®paramsãå®çŸ©ã§ããã°ãããã¯ã¯ããã«ç°¡åã§ã-IDãæ€èšŒã§ããããã«ããããã«æ£èŠè¡šçŸãå¿ èŠã§ã
äžè¬ã«ãããã«ãããã³ãŒãããŒã¹å šäœã§å°éå ·ã®æå¹æ§ã䞻匵ããããã®ããå€ãã®åãåŸãããŸãã
ã¿ã€ããããã€ããŒããã³ãã¬ãŒãæååãªãã©ã«ããŸãã¯ãã®ä»ã®ææ¡ã«åãã¯ãããŸããïŒ ããã¯ãšãŠãçŽ æŽãããããŒã«ã«ãªãã§ãããã
ããã«å¯Ÿããç§ã®åé¿çã¯ãçŸåšããã®ãããªããŒã«ãŒã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããããšã§ãã
interface TickerSymbol extends String {}
å¯äžã®åé¡ã¯ãã€ã³ããã¯ã¹ããŒãšããŠäœ¿çšããå Žåã string
ã«ãã£ã¹ãããå¿
èŠãããããšã§ãã
interface TickerSymbol extends String {}
var symbol: TickerSymbol = 'MSFT';
// declare var tickers: {[symbol: TickerSymbol]: any}; // Error: index key must be string or number
declare var tickers: {[symbol: string]: any};
// tickers[symbol]; // Type 'TickerSymbol' cannot be used as an index type
tickers[symbol as string]; // OK
ãã ããJavaScriptã¯ã€ã³ããã¯ã¹ã¿ã€ããString
ïŒå€§æåã®SïŒã§ããã°åé¡ãªãããã§ãã
var obj = { one: 1 }
var key = new String('one');
obj[key]; // TypeScript Error: Type 'String' cannot be used as an index type.
// but JS gives expected output:
// 1
@DanielRosenwasserããã«ææ¡ãããã2016幎åŸåã«å¥ã®ææ¡ãäœæãããã®ã§ããã®ã©ãã«ãæŽæ°ã§ããŸããïŒ
äžèšã®ææ¡ã確èªããããã€ãã®è³ªåãšã³ã¡ã³ãããããŸãã
ç§ãã¡ã¯åã·ã¹ãã ãå®å šã«æ¶å»ãç¶ããããšãçŽæããŠããã®ã§ãçºè¡ãããã³ãŒããçæããããã«åãšã€ãªã¢ã¹ãå¿ èŠãšããææ¡ã¯ç¯å²å€ã§ãã ãã®ã¹ã¬ããã§ãããããæããã§ã¯ãªãæ¹æ³ã§ãããçºçããããã€ãã®äŸã匷調ããŸãã
https://github.com/microsoft/TypeScript/issues/6579#issuecomment-220180091-åãã¿ã€ãã³ã°ã§é¢æ°ãšã¿ã€ããäœæããŸã
type Integer(n:number) => String(n).macth(/^[0-9]+$/)
https://github.com/microsoft/TypeScript/issues/6579#issuecomment-261519733-ãããè¡ããŸã
type CssColor = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
// ... later
setFontColorFromString(color: string) {
fontColor = color;// compile time error
if (CssColor.test(color)) {
// ^^^^^^^^ no value declaration of 'CssColor' !
fontColor = color;// correct
}
}
ç¹°ãè¿ããŸãããããã¯åå¿è ã§ã¯ãããŸããã TypeScriptã®åã¯æ§æå¯èœã§ãããåããJSãæãé·ãææ¡ã«ã¯ãåºç¯ãªã¿ã€ãããã®æŸåºããããŸãã ããã¯å®è¡ã§ããŸããã ããšãã°ãããã«ã¯åºç¯ãªã¿ã€ãæåã®æŸåºãå¿ èŠã«ãªããŸãã
type Matcher<T extends number | boolean> = T extends number ? /\d+/ : /true|false/;
function fn<T extends number | boolean(arg: T, s: Matcher<T>) {
type R = Matcher<T>
if (R.test(arg)) {
// ...
}
}
fn(10, "10");
fn(false, "false");
å®éã«ã¯ãäžè¬çãªã¿ã€ããšæ£èŠè¡šçŸã§æ€èšŒãããã¿ã€ãã¯å®éã«ã¯ç°ãªããããcorrecltyããããã®åéåãšå ±ééšåãã©ã®ããã«åŠçãããã«ã€ããŠã®ã«ãŒã«ãå¿ èŠã§ãã
type Regex_1 = / ... /;
type Regex_2 = / ... /;
type NonRegex = { ... };
type test_4 = Regex_1 & NonRegex;// compile time error
TypeScriptã¯äº€å·®ç¹ã®ã€ã³ã¹ã¿ã³ã¹åã§ãšã©ãŒãçºçããªããããããã¯æçµçãªèšèšã®äžéšã«ã¯ãªããŸããã
å šäœãšããŠãç§ãã¡ã®æãéèŠãªãã€ã³ãã¯ãåãæ£èŠè¡šçŸã2åïŒå€ç©ºéã§1åãå空éã§1åïŒ
ã¿ã€ãemitã«é¢ããäžèšã®æžå¿µãèãããšãæãçŸå®çãªè§£æ±ºçã¯ãå€ç©ºéã«åŒãèšè¿°ããããšã§ãã
// Probably put this in lib.d.ts
type PatternOf<T extends RegExp> = T extends { test(s: unknown): s is infer P } ? P : never;
const ZipCode = /^\d\d\d\d\d$/;
function map(z: PatternOf<typeof ZipCode>) {
}
map('98052'); // OK
map('Redmond'); // Error
ãã¡ãããæ£èŠè¡šçŸãå空éã«æžã蟌ãããšãã§ããŸãããå®è¡æã®æ€èšŒã¯å©çšã§ãããæå以å€ã®äœ¿çšã«ã¯åãã¹ããŸãã¯ã¢ãµãŒã·ã§ã³ãå¿ èŠã«ãªããŸãã
function map(z: /^\d\d\d\d\d$/) { }
map('98052'); // OK
map('Redmond'); // Error
function fn(s: string) {
map(s); // Error
// typo
if (/^\d\d\d\d$/.test(s)) {
// Error, /^\d\d\d\d$/ is not assignable to /^\d\d\d\d\d$/
map(s);
}
if (/^\d\d\d\d\d$/.test(s)) {
// OK
map(s);
}
}
æ°ããçš®é¡ã®ã¿ã€ãã«ã€ããŠã¯ãçæ³çã«ã¯æ¬¡ã®ãããªããã€ãã®äŸãèŠãŠã¿ãããšæããŸãã
ãã®ã¹ã¬ããã¯ãããŸããŸãªãŠãŒã¹ã±ãŒã¹ãæå³ããŸãã å ·äœçãªäŸã¯ãã£ãšãŸãã§ãã åä»ãªããšã«ããããã®äŸã®å€ãã¯å®å šã§ã¯ãªãããã§ããæå¹ãªå ¥åãæåŠããæ£èŠè¡šçŸã䜿çšããŠããŸãã
rgb(255, 0, 0)
æ§æã誀ã£ãŠæåŠãããŸãã"3e5"
誀ã£ãŠæåŠããŸãDate
ã¯ããã®ããã®ã³ã³ã¹ãã©ã¯ã¿ãŒããããŸãã å
¥åãã©ã³ã¿ã€ã ã®å€éšããã®ãã®ã§ããå Žåã¯ãåç®åãå¿
èŠã§ãfetch
ãhost
ãhttp(s?):
ãšäžç·ã«ããªãããšãæå®ãããšæ³åã§ããŸãTODOïŒRegExpã¿ã€ãã®æ©æµãåããå¯èœæ§ã®ããå®éã®ã©ã€ãã©ãªé¢æ°ãšã䜿çšããå®éã®åŒãç¹å®ããŠãã ããã
äžã€ã®æžå¿µã¯ãprecisionitisãã§ãã-誰ãã芪åã®ã§ããã¹ãŠã®éãªãã©ã«ã®åŒã³åºããå£ããDefinitelyTypedãŸã§è¡šç€ºãããã©ã€ãã©ãªå
ã®ãã¹ãŠã®é¢æ°ãžã®æ£èŠè¡šçŸã®çš®é¡ãè¿œå ãããšãã«äœãèµ·ãããŸããïŒ ããã«æªãããšã«ãå®çŸ©ãã¡ã€ã«ã®äœæè
ã¯ãæ€èšŒRegExpã®ãæ£ããã¹ãã«ããäœã§ãããããã®ã³ã³ã·ã¥ãŒããŒã«æ£ç¢ºã«åæããå¿
èŠããããŸãã
ããã«ããããã¹ãŠã®ã©ã€ãã©ãªã«URLãšããŠã®è³æ Œããã¹ãåãšããŠã®è³æ Œãé»åã¡ãŒã«ãšããŠã®è³æ Œãªã©ã®ç¬èªã®ããŒãžã§ã³ãããã2ã€ã®ã©ã€ãã©ãªãæ¥ç¶ããŠããã«ãã©ãçãããã§ããã³ã³ãã€ã©ãæºè¶³ãããã«ã¯ãåã¢ãµãŒã·ã§ã³ãæ¿å
¥ããããæ£èŠè¡šçŸãã³ããŒããå¿
èŠããããŸãã
以åã®äººéå·¥åŠã»ã¯ã·ã§ã³ã®fn
ããã«ãé¢æ°ã®åŒæ°ã以åã®æ£èŠè¡šçŸã«ãã£ãŠæ€èšŒãããŠããããšã確èªããããã§ãã¯ã«ã€ããŠã®è°è«ãããã€ããããŸããã ãã¹ããå¿
èŠãªæ£èŠè¡šçŸãããç¥ãããŠããå Žåãããã¯ç°¡åã§äŸ¡å€ãããããã«æãããŸãã ãã ããããã¯å€§ããªãifãã§ããç§ã®èšæ¶ã§ã¯ãæ€èšŒæ£èŠè¡šçŸãæäŸããåäžã®ã©ã€ãã©ãªãæãåºããŸããã æ€èšŒæ©èœãæäŸããå ŽåããããŸãããããã¯ãæäŸãããæ©èœãæ£èŠè¡šçŸã¿ã€ãã§ã¯ãªããå矩ã¿ã€ããŸãã¯ã¿ã°ä»ãã¿ã€ãã§ããããšãæå³ããŸãã
ãã®è©äŸ¡ã«å¯Ÿããå蚌ã¯æè¿ãããŸãã
äžéšã®ã©ã€ãã©ãªã¯ãããããã£åã«åŸã£ãŠãªããžã§ã¯ããåŠçããŸãã ããšãã°ãReactã§ã¯ãååãaria-
å§ãŸããã¹ãŠã®ããããã«ã¿ã€ããé©çšããŸãã
interface IntrinsicElements {
// ....
[attributeName: /aria-\w+/]: number | string | boolean;
}
ããã¯äºå®äžçŽäº€æŠå¿µã§ãïŒRegexããããã£ããŒãè¿œå ããã«Regexã¿ã€ããè¿œå ã§ãããã®éãå¯èœã§ãïŒã
TODOïŒç§ãŸãã¯èª°ãïŒïŒããã«ã€ããŠã¯å¥ã®åé¡ãéããŠãã ããã
ããçš®ã®åç®/ã¿ã°ä»ãã¿ã€ãããã£ããšããŸãããïŒ
type ZipCode = make_unique_type string;
ãã®åŸãé¢æ°ãæžãããšãã§ããŸã
function asZipCode(s: string): ZipCode | undefined {
return /^\d\d\d\d\d$/.test(s) ? (s as ZipCode) : undefined;
}
ãã®æç¹ã§ãæ¬åœã«RegExpã¿ã€ããå¿ èŠã§ããïŒ è©³çŽ°ã«ã€ããŠã¯ããã³ã³ãã€ã«æãã®ãã§ãã¯ã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
éã«ãå矩åã§ã¯ãªãæ£èŠè¡šçŸåããã£ããšããŸãããã éæ€èšŒã·ããªãªã§ããããïŒabïŒäœ¿çšãå§ããã®ã¯ããªãé åçã«ãªããŸãïŒ
type Password = /(IsPassword)?.*/;
type UnescapedString = /(Unescaped)?.*/;
declare function hash(p: Password): string;
const p: Password = "My security is g00d"; // OK
const e: UnescapedString = "<div>''</div>"; // OK
hash(p); // OK
hash(e); // Error
hash("correct horse battery staple"); // OK
ã¹ã¬ããã§ããããããšã¯ããããã®æ£èŠè¡šçŸããã¹ãã³ãŒãã®æ€èšŒã«åœ¹ç«ã€ããšã§ããããã¯ãæ¬çªã·ããªãªã§ã¯ãã³ãŒããããŒãã³ãŒãããããªãã©ã«ã§ã¯ãªãã©ã³ã¿ã€ã æäŸã®æååã«å¯ŸããŠå®è¡ãããå Žåã§ãããã¹ãæååããæ£ãã"ã ãã ããã©ã¡ãã®æ¹æ³ã§ãæ€èšŒé¢æ°ãèšè¿°ããŠãããããããã¯åç®/ã¿ã°ä»ã/ãã©ã³ãæååã®åŒæ°ã®ããã«èŠããŸãããã¹ãã®å©ç¹ã¯ããããã培åºçã«å®è¡ãããããšãç¥ã£ãŠããããšã§ãïŒãããã£ãŠããã¹ãå ¥åã®ãšã©ãŒã¯éçºãµã€ã¯ã«ã®æ©ã段éã§ãã©ã°ãç«ãŠãŸãïŒã
以äžã®åŽé¢ã«ã€ããŠè°è«ãããããã¯ãããã«ãŒã§
æ°ããã©ã³ã¿ã€ã ã¯ãå€ãã©ã³ã¿ã€ã ãããå€ãã®RegExpæ§æããµããŒãããŸãã TypeScriptã³ã³ãã€ã©ãå®è¡ãããå Žæã«å¿ããŠãæ°ããRegExpæ©èœã解æããã©ã³ã¿ã€ã ã®æ©èœã«å¿ããŠãç¹å®ã®ã³ãŒããæå¹ãŸãã¯ç¡å¹ã«ãªãå ŽåããããŸãã å®éã«ã¯ãæ°ããRegExpæ©èœã®ã»ãšãã©ã¯ããªãé£è§£ã§ããããã°ã«ãŒããããã³ã°ã«é¢é£ããŠãããããã§ã®ã»ãšãã©ã®ãŠãŒã¹ã±ãŒã¹ãšäžèŽããŠããªãããã§ãã
æ£èŠè¡šçŸã¯ç¡å¶éã®éã®äœæ¥ãå®è¡ã§ãã倧ããªæååãšã®ç §åã¯ä»»æã®éã®äœæ¥ãå®è¡ã§ããŸãã ãŠãŒã¶ãŒã¯ãã§ã«ä»ã®æ¹æ³ã§èªåèªèº«ãDOSããããšãã§ããæªæãæã£ãŠéå¹ççãªRegExpãäœæããå¯èœæ§ã¯ã»ãšãã©ãããŸããã
/\d*/
->
/.*/
ïŒïŒãåéåãå
±ééšåãããã³å±
äœäžèœçè«çã«ã¯ã /\d+/
ã¯/.+/
æ¢ç¥ã®ãµãã¿ã€ãã§ãã ãããããããRegExpãå¥ã®RegExpã®çŽç²ãªãµãã»ãããšäžèŽãããã©ãããå€æããã¢ã«ãŽãªãºã ãååšããŸããïŒç¹å®ã®å¶çŽã®äžã§ïŒãæããã«åŒã解æããå¿
èŠããããŸãã å®éã«ã¯ãRegExpesãäžèŽãããã®ã«åºã¥ããŠæé»ã®ãµãã¿ã€ãé¢ä¿ã圢æããªããŠã100ïŒ
åé¡ãããŸããã ããã¯ããããããã«æãŸããã§ãã
å²ãåœãŠå¯èœæ§ã®é¢ä¿ãæ£ããå®çŸ©ãããŠããéããåéåãšäº€å·®ã®æäœã¯ãç®±ããåºããŠãæ©èœããŸãã
TypeScriptã§ã¯ã2ã€ã®ããªããã£ãåã亀差ç¹ã§ãè¡çªããããšããããã¯never
ã«æžå°ããŸãã 2ã€ã®RegExpã亀差ããå Žåã2ã€ã®åŒã®äº€å·®ã«äžèŽããæ°ããRegExpãçæããããšããã®ã§ã¯ãªãã /a/ & /b/
ãšããŠä¿æããŸãã never
ãžã®åæžã¯ãããŸãããæååãäž¡åŽãæºããããšãã§ããªãããšã蚌æããã¢ã«ãŽãªãºã ãå¿
èŠã§ãïŒããã¯ãåè¿°ã®reïŒãµãã¿ã€ããšäžŠè¡ããåé¡ã§ãïŒã
èŠçŽãããšã次ã®ã¹ãããã¯æ¬¡ã®ãšããã§ãã
ãŠãŒã¹ã±ãŒã¹ïŒHyperscriptïŒhttps://github.com/hyperhype/hyperscriptïŒã®ãããªé¢æ°
ãã€ããŒã¹ã¯ãªããé¢æ°ã¯éåžžã h('div#some-id')
ããã«åŒã³åºãããŸã
æ£èŠè¡šçŸã®ãããªãã¿ãŒã³ãããã£ãŒã䜿çšãããšã h
ã®æ»ãã¿ã€ããå€å¥ã§ããŸããããã¯ãäŸã®å Žåã¯HTMLDivElementã«ãªããŸãã
åã·ã¹ãã ãæååãªãã©ã«ãè¿œå ã§ããå Žåãåºæ¬çã«ãã¹ãŠã®CSSããããã£ã¯ã¿ã€ãã»ãŒãã§ããå¯èœæ§ããããŸã
declare let width: number;
declare let element: HTMLElement;
element.style.height = `${width}px`;
// ...or
element.style.height = `${width}%`;
CSSã»ã¬ã¯ã¿ãŒãæ€èšŒã§ããŸãïŒ element.class#id
-æå¹ã div#.name
-ç¡å¹ïŒ
ã°ã«ãŒãã®ãã£ããã£ãïŒã©ããããããïŒæ©èœããå ŽåãLodashã®get
ã¡ãœããã¯ã¿ã€ãã»ãŒãã§ããå¯èœæ§ããããŸã
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.get(object, 'a[0].b.c');
ãããåé¡ã«ãªãå¯èœæ§ããããŸãã
interface IOnEvents {
[key: PatternOf</on[a-z]+/>]: (event: Event) => void;
}
interface IObservablesEndsOn$ {
[key: PatternOf</\$$/>]: Observable<any>;
}
ãŠãŒã¹ã±ãŒã¹ïŒé¢æ°ã®ãããªãã€ããŒã¹ã¯ãªããïŒhyperhype / hyperscriptïŒ
ãã®æ£èŠè¡šçŸã¯ã©ã®ããã«èŠããŸããããŸãã¯ããã¯ã©ã®ãããªæ€èšŒãæäŸããŸããïŒ ããã¯æ£èŠè¡šçŸããŒã¹ã®é¢æ°ã®ãªãŒããŒããŒãçšã§ããïŒ
FWIWã©ã€ãã©ãªã¯åå空éä»ãã®ã¿ã°åãåãå ¥ããä»»æã®ã¿ã°åã§ãæ©èœããŸã
> require("hyperscript")("qjz").outerHTML
'<qjz></qjz>'
ãŸããã¯ã©ã¹å€ãšIDå€ã®ç¡å¶éã®æ··åãåãå ¥ããŸã
> require("hyperscript")("baz.foo#bar.qua").outerHTML
'<baz class="foo qua" id="bar"></baz>'
CSSã»ã¬ã¯ã¿ãŒãæ€èšŒã§ããŸã
CSSã»ã¬ã¯ã¿ãŒã¯æ£èŠè¡šçŸã§ã¯æ€èšŒã§ããŸãã
ãã®æ£èŠè¡šçŸã¯ã©ã®ããã«èŠããŸããããŸãã¯ããã¯ã©ã®ãããªæ€èšŒãæäŸããŸããïŒ ããã¯æ£èŠè¡šçŸããŒã¹ã®é¢æ°ã®ãªãŒããŒããŒãçšã§ããïŒ
OPã§ã¯ãããŸããããããã§ãã HTMLDocument#createElement()
ãªãŒããŒããŒãã®ãããªãã®ã ãšæããŸããäŸïŒ
// ...
export declare function h(query: /^canvas([\.#]\w+)*$/): HTMLCanvasElement;
// ...
export declare function h(query: /^div([\.#]\w+)*$/): HTMLDivElement;
// ...
REã¯äžå®å
šã ãšæããŸãã ããã¯ãCSSã»ã¬ã¯ã¿ãŒãæ€èšŒããç¹æ®ãªã±ãŒã¹ã§ãããå€ãã®ã³ã³ããã¹ãã§éåžžã®æ¹æ³ã§äœ¿çšãããããšã«æ³šæããŠãã ããã ããšãã°ãè€éãªã»ã¬ã¯ã¿ãŒã䜿çšããŠããå Žåããã©ãŒã«ããã¯ãšããŠHTMLDocument.querySelector()
ãHTMLElement
ãè¿ãããšã¯ãŸã£ããåé¡ãããŸããã
ãã ããå®è¡å¯èœã§æçšãªéãªãŒããŒããŒãã®äŸããããã©ããã¯èå³ããããŸãã
TODOïŒRegExpã¿ã€ãã®æ©æµãåããå¯èœæ§ã®ããå®éã®ã©ã€ãã©ãªé¢æ°ãšã䜿çšããå®éã®åŒãç¹å®ããŠãã ããã
ç§ã®ãŠãŒã¹ã±ãŒã¹ã¯ãCCXTã©ã€ãã©ãªã®ãã®ã³ã¡ã³ãã§èª¬æãããã®ã§ã TickerSymbol
ãè¡šãæååããããŸãã æ£èŠè¡šçŸãã¿ãŒã³ããã§ãã¯ãããŠãããã©ããã¯ããŸãæ°ã«ããŸãããã string
ãµãã¿ã€ããšããŠæ±ãããããã«ãããã®ã§ãããå³å¯ãªå²ãåœãŠããã©ã¡ãŒã¿ãŒã¿ã€ãã®ãã§ãã¯ãªã©ãè¡ãããŸããé¢æ°åããã°ã©ãã³ã°ãããŠãããšãã«éåžžã«äŸ¿å©ã§ããã³ã³ãã€ã«æã«TickerSymbolsãCurrenciesãAssetsãªã©ãç°¡åã«è¿œè·¡ã§ããŸãããå®è¡æã«ã¯éåžžã®æååã§ãã
@omidkradããã¯ãæ£èŠè¡šçŸã§æ€èšŒãããåã§ã¯ãªããå矩åãå¿ èŠãªããã§ãã
@ m93aç§ã®å Žåã
CSSã»ã¬ã¯ã¿ãŒãæ€èšŒã§ããŸã
CSSã»ã¬ã¯ã¿ãŒã¯æ£èŠè¡šçŸã§ã¯æ€èšŒã§ããŸãã
ããŠãæ£èŠè¡šçŸã§ããããã€ãªãåãããããšãã§ããã°ãCSSæ£èŠè¡šçŸãã³ããŒã§ããŸã...ããã§ããïŒ
ïŒãã©ããïŒCSSåä»ããªããžã§ã¯ãã¢ãã«
https://drafts.cââss-houdini.org/css-typed-om/
https://developers.google.com/web/updates/2018/03/cssom
æåååã®CSSã¢ãã«ã䜿çšããããšãã欲æ±ã軜æžããå¯èœæ§ããããŸãã
el.attributeStyleMap.set('padding', CSS.px(42));
const padding = el.attributeStyleMap.get('padding');
console.log(padding.value, padding.unit); // 42, 'px'
@RyanCavanaughç¹ã«Mithrilã®å Žåãã¿ã°åã¯^([^#\.\[\]]+)
ïŒããã©ã«ãã¯"div"
ïŒã®ãã£ããã£ã°ã«ãŒããä»ããŠæœåºãããŸããã ^(${htmlTagNames.join("|")})
ãšäžèŽããã ãã§ååã§ãã ãããŠãç§ã®ææ¡ã䜿çšãããšãããã¯ç§ã®ç®çã«ã¯ååã§ãïŒ
type SelectorAttrs = "" | `#${string}` | `.${string}`;
type GetTagName<T extends string> =
T extends SelectorAttrs ? "div" :
T extends `${keyof HTMLElementTagNameMap & (infer Tag)}${SelectorAttrs}` ? T :
string;
ã€ãã³ããšå±æ§ã«é¢ããŠã¯ãäžåºŠåŠå®ãããã¿ã€ãã®åå°ã«åãæ¿ããããšãã§ããŸãã
type EventsForElement<T extends Element> =
T extends {addEventListener(name: infer N, ...args: any[]): any} ? N : never;
type MithrilEvent<E extends string> =
(E extends EventsForElement<T> ? HTMLElementEventMap[E] : Event) &
{redraw?: boolean};
type Attributes<T extends Element> =
LifecycleAttrs<T> &
{[K in `on${string}` & not LifecycleAttrs<T>](
ev: K extends `on${infer E}` ? MithrilEvent<E> : never
): void | boolean} &
{[K in keyof T & not `on${string}`]: T[K]} &
{[K in string & not keyof T & not `on${string}`]: string};
ãšããã§ããã®ã·ãŒã ã¬ã¹ãªçµ±åãšè€éãã®åé¿ããæåéãã®æ£èŠè¡šçŸãããç§ã®ææ¡ã奜ãçç±ã§ãã
ãã ããçŽç²ãªæ£èŠè¡šçŸã¿ã€ãã§ãããè¡ãæ¹æ³ã¯ããããŸããã ç§ã¯ãããææããããšæããŸãã
TODOïŒRegExpã¿ã€ãã®æ©æµãåããå¯èœæ§ã®ããå®éã®ã©ã€ãã©ãªé¢æ°ãšã䜿çšããå®éã®åŒãç¹å®ããŠãã ããã
æ²ãã£ããã®ã¯ãæåŸ ãããå¿çã¿ã€ãã説æããæååãšããŠäžãããããã®ã«åºã¥ããŠãç°ãªãæ»ãã¿ã€ããæã£ãŠããŸãã
bent('json')('https://google.com') // => Promise<JSON>
bent('buffer')('https://google.com') // => Promise<Buffer | ArrayBuffer>
bent('string')('https://google.com') // => Promise<String>
ã¡ãœãããURLãªã©ã®ä»ã®åŒæ°ãæååãšããŠåãå
¥ããŸããããããã¯ä»»æã®äœçœ®ã«è¡šç€ºãããå¯èœæ§ãããããããŠããªã³ã䜿çšããŠãã¹ãŠã®æ»ãåïŒ 'json' | 'buffer' | 'string'
ïŒãèšè¿°ããããšãããšã代ããã«ãã ããŠã³ããŸãããŠããªã³ã®urlããã³ã¡ãœããã¿ã€ããšçµã¿åããããšstring
ã«ãªããŸããã€ãŸããæåã®åŒã³åºãã§æå®ãããã¿ã€ãã«åºã¥ããŠæ»ãã¿ã€ããèªåçã«æšæž¬ããããšã¯ã§ããŸããã
@Ovyerusæ£èŠè¡šçŸã¿ã€ãã¯
type BentResponse<Encoding> = Promise<
Encoding extends "json" ? MyJsonType :
Encoding extends "buffer" ? Buffer | ArrayBuffer :
Encoding extends "string" ? string :
Response
>;
declare function bent<T extends string>(urlOrEncoding: T): (url: string) => BentResponse<T>;
http://www.typescriptlang.org/play/index.html#code/C4TwDgpgBAQhB2wBKEDOYD29UQDwFF4BjDAEwEt4BzAPigF4oAFAJwwFtydcBYAKCiCohEhWpQIAD2AJSqKACIAVqiwKoAfigBZEAClV8ACrhoALn5DhxMpSoTps + QoBGAVwBmHiC3VaYnt4sUAA + UACCLCwAhiABXj5QFgJCIrbiUjLwcoqowCx2flB5BeLJVijoWDj8NADc-PykEEQANtEs0B5uxMDkWFAuCMC4Rg5ZOSV2NAAUbiytAPIsaWJUZlBGAJQbcwsbU9RbDHRwiJWY2HhG9Y18lDIsHtFE0PFBUADeUAD67gksDbReAgKAAX34Dx8z1eOn0hhMkC + vxUWCBIPBdxm0VQIGIUBmx3odE + liErQgwCgkg2ugMWER0EY0QA7tFyFShogZspââDAotjyABbAYBgVBmAD0Eqk0XYYApADoSOx + Q0 + GCBVsgA
ç³ãèš³ãããŸããããç§ã®åé¡ã¯ãããŒã¹URLãæ€åºããããã«æååã®å
é ã§http(s):
ãç
§åããããšã«æ²¿ã£ãŠãããšæããŸãã
ãã³ãã®çœ²åã¯ã
type HttpMethods = 'GET' | 'PATCH' | ...
type StatusCode = number;
type BaseUrl = string; // This is where I would ideally need to see if a string matches http(s):
type Headers = { [x: string]: any; };
type Options = HttpMethods | StatusCode | BaseUrl | Headers;
function bent(...args: Options[]): RequestFunction<RawResponse>
function bent(...args: (Options | 'json')[]): RequestFunction<JSON>
// and so on
ãã ããæååãšããŠBaseUrl
ã䜿çšãããšãHttpMethodsãåžåãããã¿ã€ããŠããªã³ãè¿ãããæçµçã«ã¯string
ãŸãã æååãšåãããã«æã€ããšã¯ãããŒã¹URLãšããŠäœã䜿çšãããã決å®ããããã«ã ^http:
ãŸãã¯^https:
ã®ååšããã§ãã¯ãããããbentã®åäœãšãäžé©åã«ãäžèŽããŸãã
æ£èŠè¡šçŸã¿ã€ããããå Žåã¯ãBaseUrlãtype BaseUrl = /^https?:/
ãšããŠå®çŸ©ã§ããŸããããã«ãããHTTPã¡ãœãããŸãã¯å¿çãšã³ã³ãŒãã£ã³ã°ã§ã¯ãªãæååãé©åã«æ€èšŒããã string
åžåãããªãããšãçæ³çã§ããã¿ã€ãã
ãŸãã«ãç§ã¯åãã§ãã
-
Prokop Simek
2019幎10æ20æ¥03ïŒ23ïŒ30ãMichael MitchellïŒ[email protected]ïŒ
æžããŸããïŒ
ãããç³ãèš³ãããŸããããç§ã®åé¡ã¯ãã£ãš
äžèŽããhttpïŒsïŒïŒããŒã¹URLãæ€åºããããã®æååã®å é ããã³ãã®çœ²åã¯ã
ã¿ã€ãHttpMethods = 'GET' | ããããã| ... type StatusCode = number; type BaseUrl = string; //ããã¯ãæååãhttpïŒsïŒïŒtype Headers = {[xïŒstring]ïŒany;ãšäžèŽãããã©ãããçæ³çã«ç¢ºèªããå¿ èŠãããå Žæã§ãã };
ã¿ã€ãOptions = HttpMethods | StatusCode | BaseUrl | ããããŒ;
é¢æ°bentïŒ... argsïŒOptions []ïŒïŒRequestFunctioné¢æ°bentïŒ... args :(ãªãã·ã§ã³| 'json'ïŒ[]ïŒïŒRequestFunction // çã ãã ããBaseUrlãæååãšããŠäœ¿çšãããšãHttpMethodsãåžåããã
å ±çšäœãå ¥åããŸããããã¯ãæçµçã«ã¯åãªãæååã«ãªããŸãã æååãšããŠãããæã£ãŠãã
ãŸããååšããã§ãã¯ããããããäžé©åã«ãæ²ãã£ãåäœãšäžèŽããŸã
^ httpïŒãŸãã¯^ httpsïŒã®ããŒã¹ãšããŠäœã䜿çšãããã決å®ãããã
URLãæ£èŠè¡šçŸã¿ã€ããããå ŽåãBaseUrlãã¿ã€ãBaseUrl = / ^ httpsïŒïŒ/ããšããŠå®çŸ©ã§ããŸãã
ããã¯çæ³çã«ã¯ãHTTPã¡ãœããã§ã¯ãªãæååãé©åã«æ€èšŒããŸãã
å¿çãšã³ã³ãŒãã£ã³ã°ãããã³ããããæåååã«åžåããªããâ
ãã®ã¹ã¬ããã«ãµãã¹ã¯ã©ã€ãããŠããããããããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/microsoft/TypeScript/issues/6579?email_source=notifications&email_token=ABJ3U4JNK3V5MV4DJH73ZU3QPOXJFA5CNFSM4BZLAVSKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW
ãŸãã¯è³Œèªã解é€ãã
https://github.com/notifications/unsubscribe-auth/ABJ3U4PHBXO4766LK7P7UXDQPOXJFANCNFSM4BZLAVSA
ã
ç§ããŠãŒã¹ã±ãŒã¹ã«ã€ããŠèããã®ã¯ãé¢æ°ã®ãã©ã¡ãŒã¿ãŒåãæ€åºããããšã§ããã
åºæ¬çã«ãèå¥åãè¡šãæååã®æ確ã«å®çŸ©ãããæ£èŠè¡šçŸåœ¢åŒããããŸãã ãã³ã¬ãŒã¿ã䜿çšããããšãã§ããŸãããæ¡åŒµæåååã䜿çšãããšãé¢æ°ã«æž¡ãããèå¥åãè¡šãåã䜿çšã§ããŸãã
ç¹°ãè¿ãã«ãªããŸãããåæå®ãããæ¹æ³ã§èšè¿°ãããJavaScriptã³ãŒãã®äŸãå¿ èŠã§ããããããªããšãã¢ãã«åããããšããŠãããã®ïŒããã³ã¢ãã«åããæ¹æ³ããã§ã«ãããã©ããïŒããæšæž¬ã§ããŸããã
@DanielRosenwasser以äžã¯ãå ¥åã匷å¶ãããã³ãŒãã®äŸã§ãã http://www.typescriptlang.org/play/index.html#code/C4TwDgpgBAqjCSARKBeKBnYAnAlgOwHMBYAKFIGMAbAQ3XVnQiygG9SoOoxcA3a4aJn45yULBGoATAPZ5KIKAFtq + GIywAuWAmRoA5NQCcEAAwBGQwCMArAFoAZtYBMAdlsAWcvYActw2ZM7JzNJF28TCCcANgtLPXZOAHpErl5 + QWBhUXEpWXklFTw1Ji04JFQoMycAZihkqAA5AHkAFSgAQQAZTqaAdQBRRASOeu4cPgEMTOARMQkZOQVlVXVSnQq9PGlgW2pbAFd9nEk9OpSAZQAJJphO5Ga2gCF + JU6 +ã¯ãŠ++ BBL-oAlYZQciyTBYfbkYDSLAACkBnC4 + 0slFmxzWSAANHDOGBEcjRJYsNQ8JItKD8ARMSR4fCcUjZuocNRKFo8PtFJYmJTqdjcbNyDkBJJHiA0boGEwAHTLIrqACUrFICQAvqQVSQgA
@yannickglt RegExpã¿ã€ãã§ã¯ãªããå矩ã¿ã€ããå¿ èŠãªããã§ããïŒ çºä¿¡è ã次ã®ãããªãµã€ãã§æ€èšŒãããã©ã³ãã ãªåŒã³åºãã§è¡šç€ºãããããšãæåŸ ããŠããŸããã
// OK
someFunc('a9e019b5-f527-4cf8-9105-21d780e2619b');
// Also OK, but probably really bad
someFunc('a9e019b5-f527-4cf8-9106-21d780e2619b');
// Error
someFunc('bfe91246-8371-b3fa-3m83-82032713adef');
IOWæ£èŠè¡šçŸã§UUIDãèšè¿°ã§ãããšããäºå®ã¯ãæååèªäœã®åœ¢åŒã®ã¢ãŒãã£ãã¡ã¯ãã§ãããè¡šçŸããããšããŠããã®ã¯ãUUIDãç¹æ®ãªçš®é¡ã®åã§ããããã®ãããã³ã°åœ¢åŒãããŸããŸæååã§ãããšããããšã§ãã ã
ãããã£ãŠã3.7ã®Assertion Functions
ãšnominal
æ©èœã®çµã¿åããã§ãããè¡ãããšãã§ããŸãïŒïŒïŒ
nominal UUID = string
function someFunc(uuid: any): asserts uuid is UUID {
if (!UUID_REGEX.test(uuid)) {
throw new AssertionError("Not UUID!")
}
}
class User {
private static readonly mainUser: UUID = someFunc('a9e019b5-f527-4cf8-9105-21d780e2619b')
// private static readonly mainUser: UUID = someFunc(123) // assertion fails
// private static readonly mainUser: UUID = someFunc('not-a-uuid') // assertion fails
constructor(
public id: UUID,
public brand: string,
public serial: number,
public createdBy: UUID = User.mainUser) {
}
}
ããã倱æããŸããïŒ
new User('invalid-uuid', 'brand', 1) // should fail
new User('invalid-uuid' as UUID, 'brand', 1) // ð€
ãã°ããèããåŸãææ¡ããããœãªã¥ãŒã·ã§ã³ã«åé¡ããããŸãð€
asserts
ã¯ãå®è¡æã«ã®ã¿ãšã©ãŒãããªã¬ãŒã
Regex-Validation
ã¯ã³ã³ãã€ã«æãšã©ãŒãåŒãèµ·ããå¯èœæ§ããããŸã->ð
ããã§ãªããã°ããã®ææ¡ã¯æå³ããããŸãã
ç·šéïŒ
å¥ã®åé¡ïŒ someFunc(uuid: any): asserts uuid is UUID
ã¯UUIDãè¿ããã is UUID
-> true
ã¹ããŒãŸãã¯è¿ããŸãã
ãããã£ãŠããã®é¢æ°ã䜿çšããŠããã®æ¹æ³ã§UUIDãmainUser
ã«å²ãåœãŠãããšã¯ã§ããŸããã
@RyanCavanaughMithrilçšã«ããããæ£ããå ¥åããå¿ èŠããããŸãã
// <div id="hello"></div>
m("div#hello", {
oncreate(vnode) { const dom: HTMLDivElement = vnode.dom },
})
// <section class="container"></section>
m("section.container", {
oncreate(vnode) { const dom: HTMLElement = vnode.dom },
})
// <input type="text" placeholder="Name">
m("input[type=text][placeholder=Name]", {
oncreate(vnode) { const dom: HTMLInputElement = vnode.dom },
})
// <a id="exit" class="external" href="https://example.com">Leave</a>
m("a#exit.external[href='https://example.com']", {
oncreate(vnode) { const dom: HTMLAnchorElement = vnode.dom },
}, "Leave")
// <div class="box box-bordered"></div>
m(".box.box-bordered", {
oncreate(vnode) { const dom: HTMLDivElement = vnode.dom },
})
// <details></details> with `.open = true`
m("details[open]", {
oncreate(vnode) { const dom: HTMLDetailsElement = vnode.dom },
})
// alias for `m.fragment(attrs, ...children)`
m("[", {
oncreate(vnode) { const dom: HTMLElement | SVGElement = vnode.dom },
}, ...children)
ããããéçã«æåŠãããïŒ
// selector must be non-empty
m("")
// incomplete class
m("div.")
// incomplete ID
m("div#")
// incomplete attribute
m("div[attr=")
// not special and doesn't start /[a-z]/i
m("@foo")
çæ³çã«ã¯ãããããéçã«æåŠãããã®ã§ãããåªå 床ã¯ããã»ã©é«ããªãããããããªããŠãçãæ®ãããšãã§ããŸãã
// event handers must be functions
m("div[onclick='return false']")
// `select.selectedIndex` is a number
m("select[selectedIndex='not a number']")
// `input.form` is read-only
m("input[type=text][form='anything']")
// `input.spellcheck` is a boolean, this evaluates to a string
// (This is a common mistake, actually.)
m("input[type=text][spellcheck=false]")
// invalid tag name for non-custom element
m("sv")
ããã«ã¯ãã¯ããã«è€éãªåå®çŸ©ãå¿ èŠã«ãªããŸããããã«ã¯ããŠãŒã¶ãŒãåãã§ãã¯ã«å€±æããçç±ãç解ããã®ã«åœ¹ç«ã€ã«ã¹ã¿ã åãã§ãã¯å€±æã¡ãã»ãŒãžãå¿ èŠã§ãã
ä»ã®ãã€ããŒã¹ã¯ãªããã©ã€ãã©ãªãreact-hyperscriptã®ãããªãã€ããŒã¹ã¯ãªããããŒã¹ã®ãã¬ãŒã ã¯ãŒã¯ã«ãåæ§ã®æžå¿µããããŸãã
ã圹ã«ç«ãŠãã°ïŒ
@isiahmeadowsã¯ãæ£ããå ¥åã§ãã©ã³ãæååãè¿ããäœããã®åœ¢åŒã®ã»ã¬ã¯ã¿ãŒæååãã«ããŒã䜿çšããããã®ããè¯ãæ¹æ³ã§ãã ãæ°ã«å ¥ãïŒ
m(mt.div({ attr1: 'val1' }))
@ anion155ããã«m("div", {...attrs}, ...children)
ã䜿çšããå¯èœæ§ããããŸãããã€ããŒã¹ã¯ãªããã·ã¥ã¬ãŒã¯ãããŸãããïŒå
¥åãç°¡åã§ãåŠçãã¯ããã«ç°¡åã§ãïŒãä»ã§ã¯ããã«ã€ããŠå€ãã®ããšãè¡ãã«ã¯é
ãããŸãã
èšãããšããããããããŸãã ããããç§ã¯çŠããŸãã ã ãããå°ããã€èªåã®èããçºè¡šããŠãããŸãã
https://github.com/microsoft/TypeScript/issues/6579#issuecomment -542405537
ã粟å¯çãïŒç·ãç§ã¯ãã®èšèã倧奜ãïŒã«é¢ããŠã¯ã
ããŸãæ°ã«ããå¿
èŠã¯ãªããšæããŸãã
åã·ã¹ãã ã¯ãã§ã«å®æããŠããŸãã
ããã¯åºæ¬çã«ãç§ãã¡ãå€ãã®ããšã«ã€ããŠè¶
æ£ç¢ºã«ãªãããšãã§ããããšãæå³ããŸãã
ïŒSQLã®ãã¹ãŠãã¢ãã«åããã®ãšåãããã«ïŒæ¥ç¥ãããªãã©ã°= PïŒ
ããããïŒããŸãã«ãå€ãã®ïŒäººã ããã¹ãŠãå°œãããã©ã€ãã©ãªãçžäºã«äºææ§ãæããªãããã«ããã¯ã¬ã€ãžãŒãªæ¹æ³ã§ãã¹ãŠã®åæŒç®åã䜿çšããŠããã®ãèŠãããšã¯ãããŸããã ç§ã¯ãã©ã€ãã©ãªã®äœè ã¯ååã«é ãããããåŸåããããšæãã®ã奜ãã§ã...ããã§ããïŒ
æååãã¿ãŒã³å/æ£èŠè¡šçŸã§æ€èšŒãããæåååãæãã§ããããšã¯ãã£ãã«ãããŸããããã³ãŒãããŒã¹ã®åã®å®å šæ§ãé«ããã®ã«ééããªã圹ç«ã¡ãŸããã
é ã®ãŠã£ãºããããæè¿ã®1ã€ã®äŸãèããããšãã§ããŸãã ïŒãã£ãšãããããããŸãããç§ã¯å¿ããããŠããååšã§ãïŒ
ã¹ãã©ã€ãã®APIïŒæ±ºæžåŠçãã©ãããã©ãŒã ïŒãšçµ±åããå Žåã圌ãã䜿ãch_
ã«ã€ããŠcharge
ãé¢é£ã®èå¥åre_
ã«ã€ããŠrefund
é¢é£ã®èå¥åãªã©
ããããPatternOf</^ch_.+/>
ãšPatternOf</^re_.+/>
ãšã³ã³ãŒããããšããã£ãã§ãããã
ãã®ããã«ã次ã®ãããªã¿ã€ããã¹ãäœæããå Žåã
charge.insertOne({ stripeChargeId : someObj.refundId });
ãšã©ãŒãçºçããŸãã
Cannot assign `PatternOf</^re_.+/>` to `PatternOf</^ch_.+/>`
ç§ãåç®/ã¿ã°ä»ãã¿ã€ããæããŠããã®ãšåããããããããã¯ã¯ããã«é人éçã§ãšã©ãŒãçºçããããã§ãã
TSåã·ã¹ãã ã§ã¯ã¢ãã«åã§ããªããã®ãããããšãæå³ãããããç§ã¯åžžã«åç®/ã¿ã°ä»ãåãæåŸã®æ段ãšèŠãªããŠããŸãã
ãŸããã¿ã°ä»ãã¿ã€ãã¯ãã¡ã³ãã ã¿ã€ãã«æé©ã§ãã
èšåçåã¯åºæ¬çã«æ±ºããŠåœ¹ã«ç«ã¡ãŸããã
ïŒãŸããç§ã¯åèŠããããããããŸããããããã¯unique symbol
ããã ãã«åœ¹ç«ã¡ãŸãããç§ã¯å®å
šã«ééã£ãŠããããã§ã¯ãªããšæããŸããïŒ
æ€èšŒã®ããã®ãValueObjectããã¿ãŒã³ã¯ããã«æªãã®ã§ãç§ã¯ããã«ã€ããŠãããã話ãã€ããã¯ãããŸããã
以äžã以äžãæ¯èŒããŸãã
ãValueObjectããã¿ãŒã³ãææªã®è§£æ±ºçã§ãããæ¯èŒã§æ°ã«ããªãããšã¯èª°ããåæã§ããŸãããïŒ
const stripeChargeIdRegex = /^ch_.+/;
const stripeRefundIdRegex = /^re_.+/;
type StripeChargeId = PatternOf<typeof stripeChargeIdRegex>;
type StripeRefundId = PatternOf<typeof stripeRefundIdRegex>;
declare function takesStripeChargeId (stripeChargeId : StripeChargeId) : void;
declare const str : string;
takesStripeChargeId(str); //Error
if (stripeChargeIdRegex.test(str)) {
takesStripeChargeId(str); //OK
}
if (stripeRefundIdRegex.test(str)) {
takesStripeChargeId(str); //Error
}
declare const stripeChargeId : StripeChargeId;
declare const stripeRefundId : StripeRefundId;
takesStripeChargeId(stripeChargeId); //OK
takesStripeChargeId(stripeRefundId); //Error
takesStripeChargeId("ch_hello"); //OK
takesStripeChargeId("re_hello"); //Error
ãããèŠãŠã
string
éãªãã©ã«ã«ãšã£ãŠã¯ããã»ã©æªãã¯ãããŸãããconst stripeChargeIdRegex = /^ch_.+/;
const stripeRefundIdRegex = /^re_.+/;
type StripeChargeId = make_unique_type string;
type StripeRefundId = make_unique_type string;
function isStripeChargeId (str : string) : str is StripeChargeId {
return stripeChargeIdRegex.test(str);
}
function isStripeRefundId (str : string) : str is StripeRefundId {
return stripeRefundIdRegex.test(str);
}
declare function takesStripeChargeId (stripeChargeId : StripeChargeId) : void;
declare const str : string;
takesStripeChargeId(str); //Error
if (isStripeChargeId(str)) {
takesStripeChargeId(str); //OK
}
if (isStripeRefundId(str)) {
takesStripeChargeId(str); //Error
}
declare const stripeChargeId : StripeChargeId;
declare const stripeRefundId : StripeRefundId;
takesStripeChargeId(stripeChargeId); //OK
takesStripeChargeId(stripeRefundId); //Error
takesStripeChargeId("ch_hello"); //Error? Ughhhh
takesStripeChargeId("re_hello"); //Error
takesStripeChargeId("ch_hello" as StripeChargeId); //OK, BUT UNSAFE
takesStripeChargeId("re_hello" as StripeChargeId); //OK, BUT WAIT! I MESSED UP
const iKnowThisIsValid = "ch_hello";
if (isStripeChargeId(iKnowThisIsValid)) {
takesStripeChargeId(iKnowThisIsValid); //OK
} else {
throw new Error(`Wat? This should be valid`);
}
function assertsStripeChargeId (str : string) : asserts str is StripeChargeId {
if (!isStripeChargeId(str)) {
throw new Error(`Expected StripeChargeId`);
}
}
assertsStripeChargeId(iKnowThisIsValid);
takesStripeChargeId(iKnowThisIsValid); //OK
function makeStripeChargeIdOrError (str : string) : StripeChargeId {
assertsStripeChargeId(str);
return str;
}
takesStripeChargeId(makeStripeChargeIdOrError("ch_hello")); //OK
takesStripeChargeId(makeStripeChargeIdOrError("re_hello")); //OK, compiles, throws during run-time... Not good
ãããèŠãŠã
ãããããã®ææ¡ã®äž»ãªãŠãŒã¹ã±ãŒã¹ã¯æååãªãã©ã«ã§ãã
ã ãããããã¯ã²ã©ãéžæè¢ã§ãã
æ§é ã¿ã°ã¿ã€ãã¯ãåç®ã¿ã€ããšå€§å·®ãããŸããã
const stripeChargeIdRegex = /^ch_.+/;
const stripeRefundIdRegex = /^re_.+/;
type StripeChargeId = string & tag { stripeChargeId : void };
type StripeRefundId = string & tag { stripeRefundId : void };
function isStripeChargeId (str : string) : str is StripeChargeId {
return stripeChargeIdRegex.test(str);
}
function isStripeRefundId (str : string) : str is StripeRefundId {
return stripeRefundIdRegex.test(str);
}
declare function takesStripeChargeId (stripeChargeId : StripeChargeId) : void;
declare const str : string;
takesStripeChargeId(str); //Error
if (isStripeChargeId(str)) {
takesStripeChargeId(str); //OK
}
if (isStripeRefundId(str)) {
takesStripeChargeId(str); //Error
}
declare const stripeChargeId : StripeChargeId;
declare const stripeRefundId : StripeRefundId;
takesStripeChargeId(stripeChargeId); //OK
takesStripeChargeId(stripeRefundId); //Error
takesStripeChargeId("ch_hello"); //Error? Ughhhh
takesStripeChargeId("re_hello"); //Error
takesStripeChargeId("ch_hello" as StripeChargeId); //OK, BUT UNSAFE
takesStripeChargeId("re_hello" as StripeChargeId); //OK, BUT WAIT! I MESSED UP
const iKnowThisIsValid = "ch_hello";
if (isStripeChargeId(iKnowThisIsValid)) {
takesStripeChargeId(iKnowThisIsValid); //OK
} else {
throw new Error(`Wat? This should be valid`);
}
function assertsStripeChargeId (str : string) : asserts str is StripeChargeId {
if (!isStripeChargeId(str)) {
throw new Error(`Expected StripeChargeId`);
}
}
assertsStripeChargeId(iKnowThisIsValid);
takesStripeChargeId(iKnowThisIsValid); //OK
function makeStripeChargeIdOrError (str : string) : StripeChargeId {
assertsStripeChargeId(str);
return str;
}
takesStripeChargeId(makeStripeChargeIdOrError("ch_hello")); //OK
takesStripeChargeId(makeStripeChargeIdOrError("re_hello")); //OK, compiles, throws during run-time... Not good
ãããèŠãŠã
ãããããã®ææ¡ã®äž»ãªãŠãŒã¹ã±ãŒã¹ã¯æååãªãã©ã«ã§ãã
ã ãããããã¯ã²ã©ãéžæè¢ã§ãã
ãŸãããã®æ§é ã¿ã°ã¿ã€ãã®äŸã¯ãå矩ã¿ã€ãã®äŸã®ãªãã©ã«ïŒhaãpunïŒã³ããŒã¢ã³ã
å¯äžã®éãã¯ãã¿ã€ãStripeChargeId
ãšStripeRefundId
宣èšæ¹æ³ã«ãããŸãã
ã³ãŒãã¯åºæ¬çã«åãã§ãããæ§é åã¯å矩åãããåªããŠããŸãã ïŒããã¯æ¬¡ã®æçš¿ã§æããã«ããŸããèªããŸãïŒã
ããã¯ããã®ã³ã¡ã³ãã®çµè«ã«ãããŸããã ç§ã®å šäœçãªèãã®çµè«ã§ã¯ãããŸããïŒ
æååãã¿ãŒã³ã¿ã€ã/æ£èŠè¡šçŸã§æ€èšŒãããæååã¿ã€ãã¯ãåç®/æ§é ã¿ã°ã¿ã€ããããããŸã工倫ãããŠããªãã£ã
å¯èœãªéããããªããã£ãåã®ãµãã»ãããååŸããæ¹æ³ã¯ãå矩/æ§é ã¿ã°/å€ãªããžã§ã¯ãåãããåžžã«åªå ãããå¿ èŠããããŸãã
ããªããã£ãåã®ãµãã»ãããååŸããäŸã
string
ãªãã©ã«number
ãªãã©ã«ïŒ NaN, Infinity, -Infinity
é€ãïŒboolean
ãªãã©ã«bigint
ãªãã©ã«unique symbol
ããã symbol
ãµãã»ãããååŸããŠããã ãã§ãäžèšã®äŸã®ãã¡ããååã«æéãã§ããã®ã¯boolean
ã ãã§ãã å€ã¯2ã€ã ãã§ãã
éçºè
ã¯ã true
ãšfalse
ãªãã©ã«ãæã£ãŠããããšã«æºè¶³ããŠããŸããããã¯ãä»ã«æ±ãããã®ãããŸããªãããã§ãã
number
åã¯æéã§ãããå€ãéåžžã«å€ããããç¡éãšèŠãªããæ¹ãããã§ãããã
æå®ã§ãããªãã©ã«ã«ãç©ŽããããŸãã
ããããç¯å²çªå·ã¿ã€ããšNaN, Infinity, -Infinity
åé¡ãéåžžã«äººæ°ãããããããã¢ãããç¶ããçç±ã§ãã ç¡éã®ã»ããããå°ããªæéã®å€ã®ã»ãããæå®ã§ããããšã¯ååã§ã¯ãããŸããã
ç¯å²ãæå®ããããšã¯ãç¡ééåã®å€§ããªæé/ç¡éãµãã»ãããæå®ããå¿ èŠããããšãã«èª°ãã«æãæµ®ãã¶æãäžè¬ç/èªç¶ãªã¢ã€ãã¢ã®1ã€ã§ãã
bigint
ã¿ã€ãã¯åºæ¬çã«ç¡éã§ãããã¡ã¢ãªã«ãã£ãŠã®ã¿å¶éãããŸãã
ãŸããç¯å²çªå·ã¿ã€ãã®åé¡ã®äººæ°ã«ãè²¢ç®ããŠããŸãã
string
ã¿ã€ãã¯åºæ¬çã«ç¡éã§ãããã¡ã¢ãªã«ãã£ãŠã®ã¿å¶éãããŸãã
ãããŠãããããã®æååãã¿ãŒã³å/æ£èŠè¡šçŸã§æ€èšŒãããæåååã®åé¡ãéåžžã«äººæ°ãããçç±ã§ãã
æ£èŠè¡šçŸãæå®ããããšã¯ãç¡ééåã®å€§ããªæé/ç¡éãµãã»ãããæå®ããå¿ èŠããããšãã«èª°ãã«æãæµ®ãã¶æãäžè¬ç/èªç¶ãªã¢ã€ãã¢ã®1ã€ã§ãã
symbol
ã¿ã€ã...ãããç¡éã§ãã ãããŠãŸããã»ãšãã©ç¡å¶éã§ãã
ãããã symbol
ã¿ã€ãã®èŠçŽ ã¯ãã¹ãŠãã»ãšãã©ãã¹ãŠã®ç¹ã§äºãã«ã»ãšãã©é¢ä¿ããããŸããã ãããŠãã symbol
倧ããªæé/ç¡éãµãã»ãããæå®ããæ¹æ³ã¯ãããŸããïŒããšãã質åããã人ã¯èª°ãããŸããã
ã»ãšãã©ã®äººã«ãšã£ãŠããã®è³ªåã¯æå³ããããŸããã ãããè¡ãæå³ã®ããæ¹æ³ã¯ãããŸããïŒå³ïŒïŒ
ãã ããããªããã£ãã®ãµãã»ããã宣èšã§ããã ãã§ã¯ããŸã圹ã«ç«ã¡ãŸããã ç§ãã¡ãå¿ èŠã§ãã
ãããããããšã«ãTSã¯ãããå¯èœã«ããã®ã«ååæ£æ°ã§ãã
false
ã(arg : false) => void
ã«æž¡ãããšãã§ããªããšæ³åããŠã¿ãŠãã ããïŒ
çµã¿èŸŒã¿ã®çµã蟌ã¿æ¹æ³
çŸæç¹ã§ã¯ããããã®ãªãã©ã«ã«ã¯ãçµã¿èŸŒã¿ã®çµã蟌ã¿æ¹æ³ãšããŠ==
ãš===
ããããŸãã
ãªãã©ã«ããšã«æ°ããã¿ã€ãã¬ãŒããäœæããå¿ èŠããããšæ³åããŠã¿ãŠãã ããã
å矩/æ§é ã¿ã°/å€ãªããžã§ã¯ãã¿ã€ãã®åé¡ã¯ãåºæ¬çã«äžèšã®2ã€ã®åºæºãæºãããªãããšã§ãã ãããã¯ããªããã£ãåããªããžã§ã¯ãåã§ã¯ãªãäžæ Œå¥œãªåã«å€ããŸããããšã«ãããªããžã§ã¯ãåã®ããã«æ±ãããªããã°ãªããŸããã
ããŠãããã§ã¯ãæååãã¿ãŒã³ãå ¬ç§°ã¿ã°ãæ§é ã¿ã°ã®ã¿ã€ãã«ã€ããŠè©³ãã説æããŸãã
ãããã®åŒæ°ã¯ã httpsïŒ//github.com/microsoft/TypeScript/issues/15480ã«ãé©çšãããŸãã
èšåçåã¯ãã©ã€ãã©ãªéã®äºææ§ã§
ããunique symbol
ã2ã€ã®ã©ã€ãã©ãªã§
ããã¯åã«è¡ãããšã¯ã§ããŸããã
ãã€ã©ãŒãã¬ãŒãã¿ã€ãã®ã¬ãŒãããŸãã¯trust-me-operatorïŒ as
ïŒã䜿çšããå¿
èŠããããŸãã
ã¢ãµãŒã·ã§ã³ã¬ãŒãçšã®ãã€ã©ãŒãã¬ãŒããããã«å¿ èŠã«ãªããŸãã
åãã©ã€ãã©ãªéã®äºææ§ãå¿
èŠãšããªãå Žåã¯ãå矩åã䜿çšããŠãåé¡ãããŸãã...
éåžžã«é人éçã§ãã£ãŠãïŒäžèšã®äŸãåç
§ïŒã
æ§é åã®å Žåãã©ã€ãã©ãªA
ã«ããå Žåã
//Lowercase 'S'
type StripeChargeId = string & tag { stripeChargeId : void };
ãããŠãã©ã€ãã©ãªB
ã¯ã
//Uppercase 'S'
type StripeChargeId = string & tag { StripeChargeId : void };
//Or
type StripeChargeId = string & tag { isStripeChargeId : true };
//Or
type StripeChargeId = string & tag { stripe_charge_id : void };
次ã«ããã€ã©ãŒãã¬ãŒãã¿ã€ãã®ã¬ãŒããŸãã¯trust-me-operatorïŒ as
ïŒãå¿
èŠã«ãªããŸãã
ã¢ãµãŒã·ã§ã³ã¬ãŒãçšã®ãã€ã©ãŒãã¬ãŒããããã«å¿ èŠã«ãªããŸãã
ã¿ã€ããã©ã€ãã©ãªéã®äºææ§ãå¿
èŠãšããªãå Žåã¯ãæ§é åã䜿çšããŠãåé¡ãããŸãã...
éåžžã«é人éçã§ãã£ãŠãïŒäžèšã®äŸãåç
§ïŒã
æååãã¿ãŒã³ã¿ã€ãã®å Žåãã©ã€ãã©ãªA
ã«ããå Žåã
type stripeChargeIdRegex = /^ch_.+/;
type StripeChargeId = PatternOf<typeof stripeChargeIdRegex>;
ãããŠãã©ã€ãã©ãªB
ã¯ã
//Extra dollar sign at the end
type stripeChargeIdRegex = /^ch_.+$/;
type StripeChargeId = PatternOf<typeof stripeChargeIdRegex>;
//Or,
type stripeChargeIdRegex =/^ch_[a-zA-Z0-9]$/;
type StripeChargeId = PatternOf<typeof stripeChargeIdRegex>;
//Or,
type stripeChargeIdRegex =/^ch_[A-Za-z0-9]$/;
type StripeChargeId = PatternOf<typeof stripeChargeIdRegex>;
äž¡æ¹ã®ã©ã€ãã©ãªãåžžã«äž¡æ¹ã®ã©ã€ãã©ãªã®èŠä»¶ãæºããStripeChargeId
æååãçæãããšä»®å®ããŸãã ã©ã€ãã©ãªA
ã¯ãæ€èšŒããæ æ°ãã§ãã ãŸããã©ã€ãã©ãªB
ã¯ãæ€èšŒããããå³å¯ãã§ãã
ãããããããã¯äžçš®ã®è¿·æã§ãã ããããããã»ã©æªãã¯ãããŸããã
ã¿ã€ãã¬ãŒããšããŠlibraryB.stripeChargeIdRegex.test(libraryA_stripeChargeId)
ã䜿çšã§ããããã§ãã trust-me-operatorïŒ as
ïŒã䜿çšããå¿
èŠã¯ãããŸããã
ãã ããã¢ãµãŒã·ã§ã³ã¬ãŒãã«ã¯ãã€ã©ãŒãã¬ãŒããå¿ èŠã§ãã
åãã©ã€ãã©ãªéã®äºææ§ãå¿ èŠãšããªãå Žåã¯ãæååãã¿ãŒã³åã䜿çšããã®ãæé©ã§ããã人éå·¥åŠçã§ããããŸãã
ã©ã€ãã©ãªéã®äºææ§ãå¿ èŠãªå Žåã§ããæååãã¿ãŒã³ã¿ã€ãã¯æ§é ã¿ã°ã¿ã€ããããåªããŠããŸãã èããŠãã ããã
ã¢ãã«åãããŠãããã¡ã€ã³ãååã«ç解ãããŠããå Žåãè€æ°ã®å€ç«ããã©ã€ãã©ãªäœæè ãåãæ£èŠè¡šçŸãäœæããå¯èœæ§ãéåžžã«é«ããªããŸãã æ§é ã¿ã°ã¿ã€ãã䜿çšãããšãã¿ã°ã«å¿ èŠãªããããã£ãšã¿ã€ããæžã蟌ãããšãã§ããŸãã
ã¢ãã«åãããŠãããã®ãã¹ãŠã«æåå圢åŒãæå®ããæšæºãããå Žåãåºæ¬çã«ããã¹ãŠã®ã©ã€ãã©ãªäœæè ãåãæ£èŠè¡šçŸãäœæããããšãä¿èšŒãããŸãã 圌ããå¥ã®æ£èŠè¡šçŸãæžããå Žåã圌ãã¯å®éã«ã¯æšæºã«æºæ ããŠããŸããã 圌ãã®ã©ã€ãã©ãªã䜿ãããã§ããïŒ æ§é ã¿ã°ã¿ã€ãã䜿çšãããšããããã¯ãã¹ãŠäœã§ãæžãããšãã§ããŸãã ïŒèª°ãã誰ããæ°ã«ããæ§é ã¿ã°ã¿ã€ãã®æšæºãéå§ããªãéãïŒç¬ïŒ
ãã€ãã®ããã«ãèšååã¯ã¯ãã¹ããŒãžã§ã³ã®äºææ§ã§ææªã§ãã
ãããããªãã¯ããªãã®ã©ã€ãã©ãªã«ãããããŸãã¯ãã€ããŒããŒãžã§ã³ãã¶ã€ããŸãããïŒ
ã¿ã€ãã®ãã«ã©ã¬ãŒã·ã§ã³ã¯ãŸã åãã§ããïŒ
ã³ãŒãã¯ãŸã åãã§ããïŒ
ãããã ãããã¯ç°ãªãã¿ã€ãã§ãã
ã¿ã°ã¿ã€ããæ§é çã«åãã§ããéããæ§é ã¿ã°ã¿ã€ãã¯ãããŒãžã§ã³éïŒã¡ãžã£ãŒããŒãžã§ã³ã§ãïŒã§å²ãåœãŠå¯èœã§ãã
æååãã¿ãŒã³ã¿ã€ãã¯ãæ£èŠè¡šçŸãåãã§ããéããããŒãžã§ã³éïŒã¡ãžã£ãŒããŒãžã§ã³ã§ãïŒã§å²ãåœãŠå¯èœã§ãã
ãŸãã¯ãPSPACE-completeã¢ã«ãŽãªãºã ãå®è¡ããŠãæ£èŠè¡šçŸãåããã©ãããå€æããããšãã§ããŸããïŒ ãŸããæ£èŠè¡šçŸã®ã©ã®ãµãã¯ã©ã¹ãæãäžè¬çã§ããããå€æãããããã«å¯ŸããŠæé©åãããç䟡ã¢ã«ãŽãªãºã ãå®è¡ããããšãã§ããŸã...ããããããã¯å€§å€ãªåªåã®ããã«æããŸãã
æ£èŠè¡šçŸã®ãµãã¿ã€ããã§ãã¯ã¯äŸ¿å©ã§ãæååãã¿ãŒã³ã¿ã€ãã®äœ¿çšããã人éå·¥åŠçã«ãªãããšã¯ééããããŸããã ç¯å²ãµãã¿ã€ããã§ãã¯ãæ°å€ç¯å²ã¿ã€ãã®ææ¡ã«ã©ã®ããã«åœ¹ç«ã€ããšåãããã«ã
[ç·šé]
ãã®ã³ã¡ã³ãã§ã¯ã
https://github.com/microsoft/TypeScript/issues/6579#issuecomment -243338433
ãªã³ã¯ããŠãã人ã
https://bora.uib.no/handle/1956/3956
ã¿ã€ãã«ã¯ãæ£èŠè¡šçŸã®å
å«åé¡ã
[/ç·šé]
TODOïŒãã ããæååãã¿ãŒã³ã¿ã€ãã®ãã€ã©ãŒãã¬ãŒãã®éãæãå°ãªãããšãããããŸãïŒ
TODOïŒãã ããæååãã¿ãŒã³ã¿ã€ãã¯ãªãã©ã«åŒã³åºããæããããµããŒãããŠããããšãããããŸãïŒ
TODOïŒãã ããæååãã¿ãŒã³ã¿ã€ãã¯éãªãã©ã«åŒã³åºããæããããµããŒãããŠããããšãããããŸãïŒ
https://github.com/microsoft/TypeScript/issues/6579#issuecomment-542405537ã«é¢ãã詳现
TypeScriptã¯äº€å·®ç¹ã®ã€ã³ã¹ã¿ã³ã¹åã§ãšã©ãŒãçºçããªããããããã¯æçµçãªèšèšã®äžéšã«ã¯ãªããŸããã
ãªã人ã ã亀差ç¹ãçŠæ¢ãããã£ãã®ãåãããŸãããããããçŠæ¢ããããšã¯æå³ããªããšããããšã¯çµ¶å¯Ÿã«æ£ããã§ãã
ãããã£ãŠããã¹ãŠã®éæåã®åŒã³åºããå£ããŸããïŒ
ãŸãããã¹ãŠã®éãªãã©ã«åŒã³åºãã§ã¯ãããŸããã
declare function foo (arg : PatternOf</a+/>) : void;
function bar (arg : PatternOf</a+/>) : void {
//non-literal and does not break.
foo(arg);
}
bar("aa"); //OK
bar("bb"); //Error
bar("" as string); //Error, I know this is what you meant by non-literal invocation
function baz (arg : "car"|"bar"|"tar") : void {
bar(arg); //OK
}
æ£èŠè¡šçŸãšäžèŽããããšã蚌æã§ããªãéãªãã©ã«åŒã³åºããäžæããããšã¯ãå¿ ãããæªãããšã§ã¯ãããŸããã ããã¯åãªãåå®å šæ§ã®åé¡ã§ãã
ããã¯ãæååãªãã©ã«ä»¥å€ã®åŒã³åºãã倱æãããããæååãªãã©ã«ãæªããšèšã£ãŠãããããªãã®ã§ãã
æååãã¿ãŒã³ã¿ã€ã/æ£èŠè¡šçŸã§æ€èšŒãããæååã¿ã€ãã䜿çšãããšãç¡éã®æ°ã®æååãªãã©ã«ã®åéåãå®çŸ©ã§ããŸãã
éæåã«ãã䜿çšã«ã¯ãåãã¹ããŸãã¯ã¢ãµãŒã·ã§ã³ãå¿ èŠã«ãªããŸãã
ããã¯ãŸã£ããåé¡ã§ã¯ãªããšæããŸãã
çŸåšãåç®/ã¿ã°ä»ãã¿ã€ãã§ãåãã§ãã
ãŸãã¯ãæååãªãã©ã«ãæåŸ
ããé¢æ°ã«string
ãæž¡ãããšããŠããŸãã
ãŸãã¯ãå¹
ã®åºãåãå¹
ã®çãåã«æž¡ãããšããŸãã
ãã®ç¹å®ã®ã±ãŒã¹ã§ã¯ã const ZipCode = /^\d\d\d\d\d$/;
ãšZipCode.test(s)
ãã¿ã€ãã¬ãŒããšããŠæ©èœã§ããããšã瀺ããŸããã ããã¯ç¢ºãã«äººéå·¥åŠã«åœ¹ç«ã¡ãŸãã
- 解決ãããŠããåé¡ã«ã¯ãããè¯ã代æ¿æ段ã¯ãããŸããïŒãŸã èšèªã«å«ãŸããŠããªããã£ãšãããã代æ¿æ¡ãå«ãïŒ
ãŸããããŸãããã°ãåç®/æ§é ã¿ã°ã¿ã€ããããè¯ãéžæè¢ã§ã¯ãªãããšã瀺ããŸããã 圌ãã¯å®éã«ã¯ããªãæªãã§ãã
- ãã®åé¡ã¯ãå®éã®ã³ãŒãããŒã¹ã§æå³ã®ããé »åºŠã§çºçããŸã
ããŒã...ããã«ã€ããŠãè¿äºãããŠãã ãã...
- ææ¡ããã解決çã¯ãã®åé¡ãããŸã解決ããŸã
ææ¡ãããæååãã¿ãŒã³ã¿ã€ãã¯ããªãè¯ãããã§ãã
TODOïŒRegExpã¿ã€ãã®æ©æµãåããå¯èœæ§ã®ããå®éã®ã©ã€ãã©ãªé¢æ°ãšã䜿çšããå®éã®åŒãç¹å®ããŠãã ããã
ããªãã®èŠè§£ã§ã¯ãåç®/ã¿ã°ä»ãã¿ã€ãã¯ããªãã©ã«ä»¥å€ã®äœ¿çšã«ã¯ååã§ãã
ãããã£ãŠãéãªãã©ã«ã®äœ¿çšæ³ã瀺ããŠãŒã¹ã±ãŒã¹ã¯ãåç®/ã¿ã°ä»ãã¿ã€ãããããã«ããŒããŠãããããååã§ã¯ãããŸããã
ãã ããéãªãã©ã«äœ¿çšã®å Žåã§ãã
ãŸããæèµ·ãããæåéãã®ãŠãŒã¹ã±ãŒã¹ã¯ãé»åã¡ãŒã«ã®æ€èšŒãªã©ã®ã°ãããããšãè©Šã¿ãããååã«æ£ç¢ºã§ã¯ãªãæ£èŠè¡šçŸã䜿çšããããããããæºè¶³ã®ãããã®ã§ã¯ãªãã£ãããã§ãã
ãã¹ãã®èšè¿°-ããã¯ããŒãã³ãŒããããå ¥åãããçšåºŠæå³ããªããšããã§ããããã¹ãã³ãŒãã¯ããããå€ãã®ç¡å¹ãªå ¥åãæäŸããã¯ããªã®ã§ãããã¯ã»ãšãã©å¯Ÿäœæ³ã§ãã
æèµ·ãããè¯ããŠãŒã¹ã±ãŒã¹ã¯ãã©ã³ã¿ã€ã ãã¹ããæžãããšã§ããã ãããŠãããªãã¯æ£ããã§ãã圌ãã¯å®è¡æãã¹ãã®ããã«ãããã«ããããã®ç¡å¹ãªå ¥åãæããã¹ãã§ãã
ããããããã¯æååãã¿ãŒã³åããµããŒãããªãçç±ã§ã¯ãããŸããã ç¹å®ã®ãã¡ã€ã«ã§æå¹ãªå ¥åããã¹ããã誀ã£ãŠç¡å¹ãªå ¥åãäžãããå ŽåããããŸãã
ãã ããåã¬ãŒããtrust-me-operatorïŒ as
ïŒãŸãã¯å€ãªããžã§ã¯ãã䜿çšããå¿
èŠãããããããã¹ããäºåã«å€±æããããšãç¥ã代ããã«ãå®è¡æãšã©ãŒãçºçããŸãã ã
ã©ã³ã¿ã€ã ãã¹ãã«trust-me-operatorïŒ as
ïŒã䜿çšããããšã¯ãç¡å¹ãªå
¥åããã¹ãããããã«ã®ã¿äºçŽããå¿
èŠããããŸãã æå¹ãªå
¥åããã¹ãããå Žåã¯ããªãã©ã«ãåç®/æ§é ã¿ã°ã¿ã€ãã«å²ãåœãŠãããã«ããã¯ãå¿
èŠãšããªãæ¹ãæ確ã§ãã
å°æ¥ãæ£èŠè¡šçŸãå€æŽããå Žåãå²ãåœãŠå¯èœæ§ã®åé¡ã®ããã«ããã¹ããå®è¡ãããªãå ŽåããããŸãã ãã¹ãã®ã©ãã§ãas
ã ãã ãšãããããã¹ããå®è¡ãããŸã§ããããŸããã
ãããŠãå³æžé€šã®äœè
ãèªåã®å³æžé€šãããã°ããŒãã£ã³ã°ãããšãã«ã©ãã§ãas
䜿çšããå Žåãäžæµã®æ¶è²»è
ã¯ã©ãã§ããããã ãŸããã©ãã§ãas
ã䜿çšããŠãæ°ããããŒãžã§ã³ã«ã¢ããã°ã¬ãŒããããšãã«å®è¡æã®åé¡ã«ééããèªæã«é§ãããŸãããïŒ
æååãã¿ãŒã³ã¿ã€ãã䜿çšãããšãã©ãã§ãas
ã䜿çšããçç±ãå°ãªããªããã©ã€ãã©ãªã®äœæè
ãšããŠã³ã¹ããªãŒã ã®å©çšè
ã®äž¡æ¹ãå€æŽãç°¡åã«å£ãããšãã§ããŸãã
ïŒã¡ãã£ãšé·èã®åã§ãããç§ã®ãã€ã³ãã®ããã€ããããŸããã£ãããšãé¡ã£ãŠããŸãïŒã
ãŸããç§ã¯ã³ã³ãã€ã«æã®ãã¹ããããããæžãããŸãïŒãããŠãTSããŒã ãããããŠããããšãç¥ã£ãŠããŸãïŒã
ã³ã³ãã€ã«æã®ãã¹ãã§ãç¹å®ã®string
ãªãã©ã«ãæ£èŠè¡šçŸãã§ãã¯ã«å€±æ/åæ Œããããšããã¹ãã§ããã°äŸ¿å©ã§ãã çŸæç¹ã§ã¯ããããã®ã³ã³ãã€ã«æãã¹ããè¡ãããšã¯ã§ããã代ããã«ã©ã³ã¿ã€ã ãã¹ãã䜿çšããå¿
èŠããããŸãã
ãŸããã³ã³ãã€ã«æã®ãã¹ãã«å€±æ/åæ Œããå ŽåãããŠã³ã¹ããªãŒã ã®ã³ã³ã·ã¥ãŒããŒã¯ãããã®æååãªãã©ã«ïŒãŸãã¯åæ§ã®ãªãã©ã«ïŒã䜿çšããŠãæ£ããåäœãæåŸ ã§ãããšç¢ºä¿¡ããŠããŸãã
ããã¯ããã«ç§ãã¡ãããã«ã®å¡ã®ç¶æ³ãžã®éã«é£ããŠè¡ã£ãããã§ã...
ããã¯ãå®éã«ã¯ãåç®/æ§é ã¿ã°ã¿ã€ãã䜿çšããå Žåã«ããã«åœãŠã¯ãŸããŸãã äžèšã®äŸã瀺ããŠããããã«ããããã¯ã©ã€ãã©ãªé/ããŒãžã§ã³éã®äºææ§ã®ããã«ã²ã©ãæ©èœããŸã...
ãã ããæ£èŠè¡šçŸ/æååãã¿ãŒã³ã¿ã€ãã¯ããã®åé¡ã«é¥ããªãå¯èœæ§ãååã«ãããŸãïŒæšæºåãšã
ã¹ã¬ããã§ããããããšã¯ããããã®æ£èŠè¡šçŸããã¹ãã³ãŒãã®æ€èšŒã«åœ¹ç«ã€ããšã§ããããã¯ãæ¬çªã·ããªãªã§ã¯ãã³ãŒããããŒãã³ãŒãããããªãã©ã«ã§ã¯ãªãã©ã³ã¿ã€ã æäŸã®æååã«å¯ŸããŠå®è¡ãããå Žåã§ãããã¹ãæååããæ£ãã"ã ãã ããã©ã¡ãã®æ¹æ³ã§ãæ€èšŒé¢æ°ãèšè¿°ããŠãããããããã¯åç®/ã¿ã°ä»ã/ãã©ã³ãæååã®åŒæ°ã®ããã«èŠããŸãããã¹ãã®å©ç¹ã¯ããããã培åºçã«å®è¡ãããããšãç¥ã£ãŠããããšã§ãïŒãããã£ãŠããã¹ãå ¥åã®ãšã©ãŒã¯éçºãµã€ã¯ã«ã®æ©ã段éã§ãã©ã°ãç«ãŠãŸãïŒã
ãã...ãããæžãåã«ãŸããã¹ãŠãèªãã¹ãã ã£ã...
ãšã«ãããæååãã¿ãŒã³ã¿ã€ãã圹ç«ã€ããã€ãã®äŸããããŸãã
ãã®ã©ã€ãã©ãªã䜿çšãããšãHTTPã«ãŒã宣èšãªããžã§ã¯ããäœæã§ããŸãã ãã®å®£èšã¯ãã¯ã©ã€ã¢ã³ããšãµãŒããŒã®äž¡æ¹ã§äœ¿çšãããŸãã
/*snip*/
createTestCard : f.route()
.append("/platform")
.appendParam(s.platform.platformId, /\d+/)
.append("/stripe")
.append("/test-card")
/*snip*/
ãããã¯.append()
ã®å¶çŽã§ãã
/
ïŒ/
ïŒ:
ïŒãå«ããããšã¯ã§ããŸããã ãã©ã¡ãŒã¿çšã«äºçŽãããŠããŸã//
ïŒçŸåšããšã©ãŒãã¹ããŒãããããã®å®è¡æãã§ãã¯ãããããŸããã ããŠã³ã¹ããªãŒã ã®ã³ã³ã·ã¥ãŒããŒã¯ãGithub README
ãJSDocã³ã¡ã³ããèªãŸãªããŠãããããã®å¶çŽã«åŸãå¿
èŠããããŸãã ãã¹ãæžãã ãã§ãèµ€ãæ³¢ç·ãèŠããŸãã
16é²æååãè±æ°åæååã®æ£èŠè¡šçŸããããŸãã
ç§ããããæã£ãŠããŸãã
const floatingPointRegex = /^([-+])?([0-9]*\.?[0-9]+)([eE]([-+])?([0-9]+))?$/;
ç§ã¯ãããèŠãã
æŽæ°-ã3e5ãã誀ã£ãŠæåŠããŸã
ããããããŸããããã¯æŽæ°ã®æ£èŠè¡šçŸã§ã¯ãããŸãããã floatingPointRegex
ã
function parseFloatingPointString (str : string) {
const m = floatingPointRegex.exec(str);
if (m == undefined) {
return undefined;
}
const rawCoefficientSign : string|undefined = m[1];
const rawCoefficientValue : string = m[2];
const rawExponentSign : string|undefined = m[4];
const rawExponentValue : string|undefined = m[5];
const decimalPlaceIndex = rawCoefficientValue.indexOf(".");
const fractionalLength = (decimalPlaceIndex < 0) ?
0 :
rawCoefficientValue.length - decimalPlaceIndex - 1;
const exponentValue = (rawExponentValue == undefined) ?
0 :
parseInt(rawExponentValue) * ((rawExponentSign === "-") ? -1 : 1);
const normalizedFractionalLength = (fractionalLength - exponentValue);
const isInteger = (normalizedFractionalLength <= 0) ?
true :
/^0+$/.test(rawCoefficientValue.substring(
rawCoefficientValue.length-normalizedFractionalLength,
rawCoefficientValue.length
));
const isNeg = (rawCoefficientSign === "-");
return {
isInteger,
isNeg,
};
}
ç§ããã®ã³ã¡ã³ãããããŸããã
/**
Just because a string is in integer format does not mean
it is a finite number.
```ts
const nines_80 = "99999999999999999999999999999999999999999999999999999999999999999999999999999999";
const nines_320 = nines_80.repeat(4);
//This will pass, 320 nines in a row is a valid integer format
integerFormatString()("", nines_320);
//Infinity
parseFloat(nines_320);
```
*/
ããããªããšã«ã RegExp
ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãæ£èŠè¡šçŸã§æ€èšŒãããæåååã®æ©æµãåããŸãã
ä»ãããã§ãã
new(pattern: string, flags?: string): RegExp
ããããç§ãã¡ã¯æã€ããšãã§ããŸããã
new(pattern: string, flags?: PatternOf</^[gimsuy]*$/>): RegExp
TL; DRïŒèªãã§ãã ãããããããç§ã¯ããã«å€å€§ãªåªåãæããŸããïŒcry :)
string
ã¿ã€ãã®å€§ããªæé/ç¡éãµãã»ãããå®çŸ©ããæãèªç¶ãªæ¹æ³ã§ããä»ã®äººãæèµ·ããå€ãã®ãŠãŒã¹ã±ãŒã¹ã¯ãæ¢åã®ã©ã€ãã©ãªã«åãããã«æååãã¿ãŒã³ã¿ã€ããå°å ¥ããããšèããŠããŸããã ãããŠããã¯TSããŒã ã説åŸããŠããããã«ã¯èŠããŸããã
å€ãã®å Žåããããã®æ¢åã®ã©ã€ãã©ãªã¯ãå ¥åãæ€èšŒããããã«æ£èŠè¡šçŸãããŸã䜿çšããŠããªãããã«æããŸãã ãŸãã¯ãæ£èŠè¡šçŸã䜿çšããŠç°¡åãªæ€èšŒãå®è¡ããŸãã 次ã«ãããè€éãªããŒãµãŒã䜿çšããŠå®éã®æ€èšŒãå®è¡ããŸãã
ããããããã¯æååãã¿ãŒã³ã¿ã€ãã®å®éã®æå¹ãªãŠãŒã¹ã±ãŒã¹ã§ãïŒ
確ãã«ãã§å§ãŸãããšãæåå/
ãã§çµãã£ãŠããªã/
ãé£ç¶ããŠå«ãŸããŠããŸãã/
ããããŠå«ãŸããŠããŸãã:
"ãæž¡ããŸãHTTPãã¹æ£èŠè¡šçŸãã ãã ããããã¯ããã®æ£èŠè¡šçŸãæž¡ãå€ã®ã»ãããæå¹ãªHTTPãã¹ã®
ããã«äžã«ã¯ã ?
ã䜿çšãããŠããªãã #
ã䜿çšãããŠããªããäžéšã®æåããšã¹ã±ãŒããããŠãããªã©ããã§ãã¯ããå®éã®URLãã¹ããŒãµãŒããããŸãã
ãããããã®åçŽãªæååãã¿ãŒã³ã¿ã€ãã䜿çšãããšãã©ã€ãã©ãªã®ãŠãŒã¶ãŒãééããå¯èœæ§ã®ããäžè¬çãªåé¡ã®å€§èŠæš¡ãªã¯ã©ã¹ããã§ã«æé€ãããŠããŸãã ãŸããã³ã³ãã€ã«æã«ãåé€ããŸããã
?
ãã¯ãšãªæååã®å§ãŸãã§ããããšãç¥ã£ãŠããçµéšãè±å¯ãªããããŠãŒã¶ãŒãHTTPãã¹ã§?
ã䜿çšããããšã¯ãã£ãã«ãããŸããã
ç§ã¯ããªãããã®ãŠãŒã¹ã±ãŒã¹ããã§ã«ç¥ã£ãŠ
ãã®ã¹ã¬ããã¯ãããŸããŸãªãŠãŒã¹ã±ãŒã¹ãæå³ããŸãã å ·äœçãªäŸã¯ãã£ãšãŸãã§ãã åä»ãªããšã«ããããã®äŸã®å€ãã¯å®å šã§ã¯ãªãããã§ããæå¹ãªå ¥åãæåŠããæ£èŠè¡šçŸã䜿çšããŠããŸãã
ãããã£ãŠã確ãã«ãææ¡ãããæ£èŠè¡šçŸã®å€ãã¯ãå®å
šãã§ã¯ãããŸããã
ãããã圌ããæå¹ãªå
¥åãæåŠããªãéããããã¯å€§äžå€«ã§ãããïŒ
ç¡å¹ãªå
¥åãèš±å¯ããŠã倧äžå€«ã§ãããïŒ
å®è¡æã«ãå®éã®ãããŒãµãŒã§å®å
šãªæ€èšŒãåŠçã§ããããã§ãã
ãŸããã³ã³ãã€ã«æã®ãã§ãã¯ã«ãããããŠã³ã¹ããªãŒã ãŠãŒã¶ãŒã«å
±éããå€ãã®åé¡ãæé€ããçç£æ§ãåäžãããããšãã§ããŸãã
æå¹ãªå ¥åãæåŠããäŸã¯ãæå¹ãªå ¥åãæåŠããã«ç¡å¹ãªå ¥åãèš±å¯ããããã«ãç°¡åã«å€æŽã§ããå¿ èŠããããŸãã
ãšã«ãããæååãã¿ãŒã³ã¿ã€ãã®äº€å·®ã¿ã€ãã¯éåžžã«äŸ¿å©ã§ãïŒ
ç§ã®.append()
äŸã¯ã次ã®ããã«æžãããšãã§ããŸãã
append (str : (
//Must start with forward slash
& PatternOf</^\//>
//Must not end with forward slash
& PatternOf</[^/]$/>
//Must not have consecutive forward slashes anywhere
& not PatternOf</\/\//>
//Must not contain colon
& PatternOf</^[^:]+$/>
)) : SomeReturnType;
not PatternOf</\/\//>
ã¯ã次ã®ããã«ããªããŸãã
PatternOf</^((([/])(?!\3))|[^/])+$/>
ããããããã¯ã¯ããã«è€éã§ã
åºç¯ãªãã¢ã³ã¹ãã¬ãŒã·ã§ã³ãããããšãã @ AnyhowStep ã ããããèªãã§ãããããšãæ¹å€ãããã£ãã®ã§ããããšãŠãåèã«ãªããŸããïŒ
æååãã©ã¡ãŒã¿ãŒã§ãã£ã±ãã®å éšAPIãå ¥åããã®ã«èŠåŽããããšããããããå¿ ç¶çã«å®è¡æã«ã¹ããŒãããå€ãã®æ¡ä»¶ãçºçããŸãã å¿ ç¶çã«ãç§ã®æ¶è²»è ã¯ãããã®ãã¿ãŒã³ãã§ãã¯ãè€è£œããå¿ èŠããããŸãã圌ãã¯äŸå€ãæãŸãªãã®ã§ã倱æãåŠçããããã®ç¹å¥ãªæ¹æ³ãæãã§ããŸãã
// Today
function createServer(id: string, comment: string) {
if (id.match(/^[a-z]+-[0-9]+$/)) throw new Error("Server id does not match the format");
// work
}
// Nicer
function createServer(id: PatternOf</^[a-z]+-[0-9]+$/>, comment: string) {
// work immediately
}
æååãšãã¿ãŒã³ã®äžçã§ã¯ãäžè¬çãªstring
ã¯unknown
ãšã»ãšãã©åãã§ãããã©ã³ã¿ã€ã ãã§ãã¯ãåªå
ããŠå€ãã®åå®å
šæ§ãæé€ããæ¶è²»ããéçºè
ã«äžäŸ¿ããããããŸãã
èšåãããããã€ãã®ãŠãŒã¹ã±ãŒã¹ã§ã¯ãæ£èŠè¡šçŸã®å°ããªãµãã»ããã®ã¿ãå¿ èŠã«ãªããŸããããšãã°ããã¬ãã£ãã¯ã¹ã®äžèŽã§ãã
ããã¯ãå¯å€ååŒæ°ã®çš®é¡ïŒ5453ãæååãªãã©ã«åãæ¡æ£ããéã®åæšè«ãªã©ã®ããäžè¬çãªTSèšèªæ©èœã䜿çšããŠå®è¡ã§ããå¯èœæ§ããããŸãã
å°æ¥ã®æ¶æž¬ïŒ
const x: ['a', 'b', 'c'] = [...'abc'] as const;
type T = [...'def']; // ['d', 'e', 'f'];
type Guard<T extends string> =
[...T] extends [...'https://', ...any[]] ? Promise<any> : never;
declare function secureGET<
T extends string
>(url: T): Guard<T>;
const x = secureGET('https://a.com');
x.then(...) // okay
const z = secureGET('http://z.com');
z.then(...); // error
type NaturalNumberString<T extends string> =
[...T] extends ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9')[] ? T : never;
èšåãããããã€ãã®ãŠãŒã¹ã±ãŒã¹ã§ã¯ãæ£èŠè¡šçŸã®å°ããªãµãã»ããã®ã¿ãå¿ èŠã«ãªããŸããããšãã°ããã¬ãã£ãã¯ã¹ã®äžèŽã§ãã
ç§ã¯ãŸã ç§ã®ææ¡ãæ¯æãæã®ãªãèšèªã®éåžžã«å°ããªã¹ãŒããŒã»ããã§ããããµãã»ããåãšåçæ§ãåççã«å¹ççã«ãã§ãã¯ã§ããŸãã ãããŠãããŸã§ã®ãšãããTSããŒã ãæ±ããæ倧ã®æžå¿µã§ãããä»»æã®æ£èŠè¡šçŸã®ããã©ãŒãã³ã¹ã®åŽé¢ã«å¯ŸåŠããä»ã®ææ¡ã¯èŠãããšããããŸããã
ã¹ã¿ãŒããªãŒèšèªã®åé¡ã¯ããã®ååã瀺ãããã«ãã¹ã¿ãŒã䜿çšã§ããªãããšã§ããããã«ãããURLãªã©ã®æ€èšŒãå°é£ã«ãªããŸãã ãã®äžãã»ãšãã©ã®äººã¯ããããæã欲ãããããããããšãã¥ã¬ãŒãããããã«ä»»æã®æ°ã®ç¹°ãè¿ãã·ãŒã±ã³ã¹ã䜿çšããã ãã§ããããµãã»ããããã§ãã¯ããã®ãé£ãããªããŸãã
ãããŠãã»ãšãã©ã®éåžžã®DFAè¡šçŸå¯èœãªæ£èŠè¡šçŸã®ããã©ãŒãã³ã¹ã¯ããã»ã©æªãã¯ãªãããµã/ã¹ãŒããŒã»ããã«ã€ããŠãããããã§ãã¯ããããšãå¯èœã§ãã
ãã ãã *
ãååŸããããšã¯ã§ããŸãã
const str : PatternOf</ab+c/> | PatternOf</ac/>
@TijmenWç§ã®ææ¡ãããå°ã詳ããèªãã§ãã ãã-ããã«ã¯ããã€ãã®é ãããçè«çæ ¹æ ãšããããå®éã«å®çšçã«ããããã€ãã®å°ããªæ©èœããããŸãã æã®ãªãææ³ãæå®ããããšã«çŽæ¥éå®ãããã®ã§ã¯ãªããå°ããªã¹ãŒããŒã»ãããæ¡åŒµãããŠãç§ã®ã»ãã¢ããã³ã¹ã®ãŠãŒã¹ã±ãŒã¹ã«å®çšçã«åœ¹ç«ã€ããã«ãªããŸããã ç¹ã«ãããªããè¡ãããšãã§ããŸãstarof ('a' | 'b' | ...)
åã
ã®æåã®ããã«ãããªãã䜿çšããããšãã§ããŸãstring
ãšåçãšããŠstarof UnionOfAllCodePoints
ïŒçè«çã«ã¯ãããã¯ãã¯ãåå§äœã£ãŠããªãå¹æã§ïŒã
ãŸããæ£èŠèšèªãä»ã®æ£èŠèšèªãäžèŽãããã®ã®ãµãã»ãããšäžèŽãããã©ããããã§ãã¯ããããšã¯NPå®å
šã§ãããäžè¬çãªãµãã°ã©ãåååé¡ãšåçã§ãã ããããæšæºã®æ£èŠèšèªã ããå®è¡ã§ããªãçç±ã§ãããçè«çãªèšç®ã®è€éããæããããã«ã starof
ãå¯èœãªéãå¶éããããšããçç±ã§ãã
TODOïŒRegExpã¿ã€ãã®æ©æµãåããå¯èœæ§ã®ããå®éã®ã©ã€ãã©ãªé¢æ°ãšã䜿çšããå®éã®åŒãç¹å®ããŠãã ããã
ããã¯ãŸã£ããæ°ããã©ã€ãã©ãªãªã®ã§ãäžç²ã®å¡©ã§ãããåããŸããã httpsïŒ//github.com/ostrowr/ts-json-validatorã®ãããªã©ã€ãã©ãªã¯ãæ£èŠè¡šçŸã¿ã€ãã®ãããªãã®ã§ã¯ããã«äŸ¿å©ã«ãªããŸãã
ã©ã€ãã©ãªã®ç®çã¯ãTypescriptã¿ã€ããšJSONã¹ããŒãã®ãã¢<T, s>
ããã«çæããããšã§ãã
s
ãæ€èšŒã§ãããã¹ãŠã®ã¿ã€ãã¯ã T
å²ãåœãŠãããšãã§ããŸããs
ã«å¯ŸããŠå®è¡ãããšã T
å²ãåœãŠå¯èœãªã¿ã€ããã§ããã ãå°ãªããªããæ€èšŒã«å€±æããŸããæ£èŠè¡šçŸã¿ã€ãã¯ãæ€èšŒãããã¿ã€ããå°ãªããšã次ã®ããŒã¯ãŒãã«ã€ããŠããå³å¯ã«ãªãããšãèš±å¯ããããšã«ãããïŒ2ïŒã®å³å¯ããæ¹åããŸãã
format
patternProperties
propertyNames
TODOïŒRegExpã¿ã€ãã®æ©æµãåããå¯èœæ§ã®ããå®éã®ã©ã€ãã©ãªé¢æ°ãšã䜿çšããå®éã®åŒãç¹å®ããŠãã ããã
ãã¹ãŠã®Excelã€ã³ã¿ãŒãã§ã€ã¹ã©ã€ãã©ãªã¯ãåã®æ€èšŒãA1
ãŸãã¯A5:B7
ãšããŠäœ¿çšã§ããŸãã
ããããã£ããŒ/æ£èŠè¡šçŸæååã€ã³ãã¯ãµãŒ
äžéšã®ã©ã€ãã©ãªã¯ãããããã£åã«åŸã£ãŠãªããžã§ã¯ããåŠçããŸãã ããšãã°ãReactã§ã¯ãååã
aria-
å§ãŸããã¹ãŠã®ããããã«ã¿ã€ããé©çšããŸããinterface IntrinsicElements { // .... [attributeName: /aria-\w+/]: number | string | boolean; }
ããã¯äºå®äžçŽäº€æŠå¿µã§ãïŒRegexããããã£ããŒãè¿œå ããã«Regexã¿ã€ããè¿œå ã§ãããã®éãå¯èœã§ãïŒã
ç§ã¯ãããããã§èµ·ãã£ãŠãããã¹ãŠã«å°ãçŽäº€ããŠããããšãç¥ã£ãŠããŸããããŠã§ãºãªãŒã¯ããªããç§ãã¡ã®å
¥åã䜿ãããšãã§ãããšæããŸããã ããã¯ãããŸããŸãªçç±ã§ãã¡ããªãã¯ã§çºçãç¶ããŸãã ã³ã³ããŒãã³ãã©ã€ãã©ãªãšããŠã data-
aria-
å±æ§ãšæ¶è²»è
ãžã®
äœããæäŒãã§ããããšããããŸããããç¥ãããã ããã ð
import * as React from 'react';
// Want to reflect the same aria- and data- attributes here that JSX compiler allows in this interface:
interface TestComponentProps {
someProp?: number;
}
const TestComponent: React.FunctionComponent<TestComponentProps> = () => {
return null;
}
const ConsumerComponent: React.FunctionComponent = () => {
// The React component interface allows for 'data-' and 'aria-' attributes, but we don't have any typesafe way of
// elevating that interface or instantiating props objects that allow the same attributes. We just want to be able to
// define component interfaces that match what the React component interface allows without opening it up to 'any' and
// giving up all type safety on that interface.
const testComponentProps: TestComponentProps = {
someProp: 42,
'data-attribute-allowed': 'test'
};
return (
<TestComponent
someProp={42}
// 'data-' and 'aria-' attributes are only allowed here:
data-attribute-allowed={'data-value'}
aria-attribute-allowed={'aria-value'}
{...testComponentProps}
/>
)
}
TODOïŒRegExpã¿ã€ãã®æ©æµãåããå¯èœæ§ã®ããå®éã®ã©ã€ãã©ãªé¢æ°ãšã䜿çšããå®éã®åŒãç¹å®ããŠãã ããã
cronãžã§ãã ïŒãããèšåãããŠããªãããšã«éåžžã«é©ããïŒ
^((\*|\d+((\/|\-|,){0,1}(\d+))*)\s*){6}$
ããã«2ã»ã³ããæå
¥ããã ãã§ããHTMLã®id
å±æ§ãšããŠäœ¿çšãããå°éå
·ãæ€èšŒãããReactãããžã§ã¯ãã«åãçµãã§ããŸãã ããã¯ã次ã®ã«ãŒã«ãæºããå¿
èŠãããããšãæå³ããŸããæºãããªãå ŽåãäºæããªãåäœãçºçããŸãã
èšãæãããšïŒ
interface Props {
id: PatternOf</[^ ]+/>;
}
å¥ã®äŸïŒ '<namespace>/<name>[@<version>]'
圢åŒã§æååãæåŸ
ãããsanctuary-type-identifiers
ãŠãŒã¹ã±ãŒã¹ïŒ Navigator.registerProtocolHandler()
ãããªæåååã®DOMAPIã
MDNã®åŒçšïŒ
ã»ãã¥ãªãã£äžã®çç±ããã
registerProtocolHandler()
ã¯ç»é²ã§ããã¹ããŒã ãå¶éããŸããã«ã¹ã¿ã ã¹ããŒã ã¯ã次ã®æ¡ä»¶ãæºãããŠããéãç»é²ã§ããŸãã
- ã«ã¹ã¿ã ã¹ããŒã ã®ååã¯
web+
å§ãŸããŸã- ã«ã¹ã¿ã ã¹ããŒã ã®ååã«ã¯ã
web+
ãã¬ãã£ãã¯ã¹ã®åŸã«å°ãªããšã1æåãå«ãŸããŸã- ã«ã¹ã¿ã ã¹ããŒã ã®ååã«ã¯å°æåã®ASCIIæåããå«ãŸããŠããŸããã
ã€ãŸãã Navigator.registerProtocolHandler()
ã¯ãæ¢ç¥ã®string
ãŸãã¯ã«ã¹ã¿ã string
ãããããæ³å®ããŠããŸãããç¹å®ã®ã¹ããŒãã«æºæ ããŠããå Žåã«éããŸãã
CSSTypeã®CSSã«ã¹ã¿ã ããããã£ã¯ã --
ã§å§ãŸãããããã£ãé€ããã¹ãŠã®ããããã£ã«ã¯ããŒãºãã¿ã€ããæäŸããå¥ã®ãŠãŒã¹ã±ãŒã¹ã§ãã
interface Properties {
// ....
[customProperty: /--[a-z][^\s]*/]: number | string;
}`
ãããæ¹è¯ã¿ã€ããšåããã©ãã誰ãã«æããŠããããŸããïŒ https://github.com/microsoft/TypeScript/issues/7599
@ gautam1168çè«çã«ã¯åãªããµãã»ããã§ãããæåååãå ·äœçã«
èšåãããããã€ãã®ãŠãŒã¹ã±ãŒã¹ã§ã¯ãæ£èŠè¡šçŸã®å°ããªãµãã»ããã®ã¿ãå¿ èŠã«ãªããŸããããšãã°ããã¬ãã£ãã¯ã¹ã®äžèŽã§ãã
ç§ã¯ãŸã ç§ã®ææ¡ãæ¯æãæã®ãªãèšèªã®éåžžã«å°ããªã¹ãŒããŒã»ããã§ããããµãã»ããåãšåçæ§ãåççã«å¹ççã«ãã§ãã¯ã§ããŸãã ãããŠãããŸã§ã®ãšãããTSããŒã ãæ±ããæ倧ã®æžå¿µã§ãããä»»æã®æ£èŠè¡šçŸã®ããã©ãŒãã³ã¹ã®åŽé¢ã«å¯ŸåŠããä»ã®ææ¡ã¯èŠãããšããããŸããã
ãã®ã³ã¡ã³ãã§ã¯ã
https://github.com/microsoft/TypeScript/issues/6579#issuecomment -243338433
ãªã³ã¯ããŠãã人ã
https://bora.uib.no/handle/1956/3956
ã¿ã€ãã«ã¯ãæ£èŠè¡šçŸã®å å«åé¡ã
ãããã
https://www.sciencedirect.com/science/article/pii/S0022000011001486
ïŒãã¡ãããJSã®æ£èŠè¡šçŸã¯éæ£èŠè¡šçŸã§ãïŒ
@AnyhowStepããã¯starof
å¶éã解é€ããããã«å¿ããŠãã®å¶éãå€æŽããŸãã æ°åŠã¯å°ãæœè±¡çã§ãããããã¯ããããå
·äœçã«ïŒãããã®åã䜿çšããŠããªãã誰ãããæ£åŒãªèšèªã«ç²ŸéããŠããïŒãå®éã«é©çšããããã¯äžæã ã®ã§ãç§ã¯ãå¶éãç¹åŸŽä»ããããè¯ãæ¹æ³ãããããš
ãŸãããããšã¯å¥ã«ããã®ãããªãã®ãã¢ãã«åããããã®æŒç®åãšããŠã starof
ããè¯ã代æ¿æ段ã匷ãæãã§ããŸãã
èå³ããããŸãïŒæ£èŠè¡šçŸã®å
å«/å
å«ã決å®ããããšã¯å¯èœã§ããïŒ ãŠã£ãããã£ã¢ã«
ããã¯ãã®æ©èœã«åœ±é¿ããŸãïŒçµã蟌ã¿ïŒïŒ
if (Gmail.test(candidate)) {
// candidate is also an Email
}
@nikeee決å®å¯èœã§ã¯ããããçŸå®çã«ããã®ã«ååã§ã¯ãããŸããã äºæ¬¡æéã§ããããã®ã¹ã±ãŒã«ã§ã¯äžè¬ã«é ãããŸãã TSã§ã¯ãããŸããããç§ã¯åæ§ã®åé¡ã«ã€ããŠããã€ãã®èæ¯ãæã£ãŠããŸãã
åŸæ¹åç §ã«çŽé¢ããŠãç§ã¯ããããŸã 決å®å¯èœã§ãããšæãããæªãã¯ãªãã«ããŠãææ°é¢æ°çã§ããå¯èœæ§ãé«ãã ãããããã ã®ç¥èã«åºã¥ããæšæž¬ã§ãã
ãããæ確ã«ããŠãããŠããããšãïŒ
äºæ¬¡æéã§ããããã®ã¹ã±ãŒã«ã§ã¯äžè¬ã«é ãããŸãã
ã ããç§ã¯ãããèšç®äžå®è¡å¯èœãã©ãããå°ããã®ã§ãããã§ã¯ãªããšæããŸãã
åãããšãå¹³çã«ãåœãŠã¯ãŸãå Žåãããã¯ãã®æ©èœã®ã»ãšãã©ãã¹ãŠã®ããããã£ãå®è¡äžå¯èœã§ããããšãæå³ããŸãããïŒ ç§ãééã£ãŠããå Žåã¯èšæ£ããŠãã ããããã ããæ®ã£ãŠããã®ã¯ã¡ã³ããŒã·ããã ãã®ããã§ãã ããã ãã§ã¯åœ¹ã«ç«ããªããšæããŸãã
@nikeeeãã®ãã¿ãŒã³ã¯ãæ¯èŒããããã¹ãŠã®ã¿ã€ãã®æåéããã¹ãŠã®ããããã£ã«å¯ŸããŠãã§ãã¯ãããããšãèŠããŠãã䟡å€ããããŸãã ãŸããæ£èŠè¡šçŸããããã£ãæã€åã®å Žåãæ£èŠè¡šçŸãå¥ã®æ£èŠè¡šçŸãäžèŽãããã®ã®ãµãã»ãããšäžèŽãããã©ãããèšç®ããå¿ èŠããããŸããããã¯ãããèªäœãããªãè€éãªç£ã§ãã
ããã¯äžå¯èœã§ã¯ãªãããã é£ããã ãã§ãããããå®çŸå¯èœã«ãããã®ã§ããã°ãå¶éããå¿ èŠããããŸãã ïŒ1ã€ã«ã¯ãJSæ£èŠè¡šçŸã¯æ©èœããŸãããååã«æ¡åŒµå¯èœã§ããã ãã§ãªããæè»æ§ããããŸããïŒ
ç·šéïŒç§ã¯ãããç¹°ãè¿ããããšæããŸãïŒæ確ã«ããããã«ãç§ã¯TSããŒã ã«æå±ããŠããŸããã ç§ã¯CSã¢ã«ãŽãªãºã ã®èšèšã«ãŸãšããªããã¯ã°ã©ãŠã³ããæã£ãŠããŸãã
ããŒããå€åããªãã¯ãéåžžã®ãæ£èŠè¡šçŸã®ãéå®ãããããµãã»ãããããµããŒãã§ããªãã§ãããã ãŠãŒã¹ã±ãŒã¹ãèãããšããããŸã§ã®ãšããæ£èŠè¡šçŸã¯éåžžã«åçŽã§ããâŠïŒè²ãé»è©±çªå·ãªã©ïŒ
ãµãã»ããã®ã¿ããµããŒãããUXãã©ã®ããã«èšèšã§ããŸããïŒ RegExã®æ©èœXãæ©èœããããšã¯ãŠãŒã¶ãŒã«ã¯ããŸãæ確ã§ã¯ãªããããããŸããããYã¯æ©èœããŸããã
ãããšâŠããããæ£èŠè¡šçŸããšåŒã°ãªãã§ãã ããâåå¿è ã®ããã«ã ãã¶ãããã¿ãŒã³ãããã³ã°ãããããïŒsee_no_evil :ã ãããããããããããç°¡åãªäœæ¥ã§ã¯ãããŸããâŠ
ãã®ãããªéæ£èŠè¡šçŸã®æ§æã¯ã©ãã§ããïŒ
type TLD = 'com' | 'net' | 'org';
type Domain = `${string}.${TLD}`;
type URL = `${'http'|'https'}://${Domain}`;
const good: URL = 'https://google.com'; // âïž
const bad: URL = 'ftp://example.com'; // âïž TypeError: 'ftp' is not assignable to type 'http' | 'https'
ç§ã®èãã§ã¯ãããã¯åã·ã¹ãã ã«éåžžã«ããŸãé©åããŸãã ãªãã·ã§ã³ã®äžèŽãªã©ã«ç°ãªãæ§æãè¿œå ã§ããŸãã
type SubDomain = `${string}.`;
type Domain = `${SubDomain}?${string}.${TLD}`;
æ°éè©ã貪欲ãªæŒç®åã®ãµããŒããè¿œå ãããšãéåžžã«å ç¢ãªãã®ãåŸãããŸããéçºè ãããã䜿çšããå¯èœæ§ã®ããã»ãšãã©ã®ãŠãŒã¹ã±ãŒã¹ã«ã¯ãããããããã§ååã ãšæããŸãã
ãã®ã¢ãããŒãã®æ¹ããŠãŒã¶ãŒãã¬ã³ããªãŒã ãšæããŸãã ãã ããåã®ç®è¡æŒç®ãšåçã®ããã§ãã
https://github.com/microsoft/TypeScript/issues/15645#issuecomment-299917814ããã³https://github.com/microsoft/TypeScript/issues/15794#issuecomment-301170109ã«ãããšããããè¡ããªãããšã¯èšèšäžã®æ±ºå®ã§ããã¿ã€ãã®ç®è¡ã
ç§ã誀解ããŠããªããã°ããã®ã¢ãããŒãã¯ç°¡åã«å·šå€§ãªã¿ã€ããäœæããããšãã§ããŸãã æ€èšïŒ
type TLD = 'com' | 'net' | 'org' | 'ly' | 'a' | 'b' | 'c' | 'd';
type Foo = `${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}`;
type Bar = `${Foo}${Foo}${Foo}${Foo}${Foo}`
ïŒããã¯ãå®è£ ãå ±çšäœåã䜿çšããããšãåæãšããŠããŸããå¥ã®/ããè€éãªå®è£ ã§æ©èœããå¯èœæ§ããããŸãïŒ
DislaimerïŒç§ã¯TSããŒã ã®äžå¡ã§ã¯ãªããTSã«åãçµãã§ããŸããã ã¡ããã©ç§ã®2cã
@rozzzly @nikeeeããã¯å€ããå°ãªããç§ã®ææ¡ã®æ¬è³ªã§ãããããã€ãã®å°ããªæ©èœãæ¬ ããŠããŸãã ç§ã¯æ£èŠè¡šçŸïŒæ£åŒãªèšèªã®æŠå¿µïŒã®å€§èŠæš¡ãªãµãã»ããã«åºã¥ããŠãããæ£èŠè¡šçŸãªã©ã®æå³ã§ã®æ£èŠè¡šçŸã§ã¯ãªããããæ£èŠè¡šçŸãããã¯ããã«åŒ·åã§ã¯ãããŸããããä»äºãéè¡ããã®ã«åå匷åã§ãã
ãã®ã¢ãããŒãã®æ¹ããŠãŒã¶ãŒãã¬ã³ããªãŒã ãšæããŸãã ãã ããåã®ç®è¡æŒç®ãšåçã®ããã§ãã
æ°åŠã«ããã°ãããåãå¥ã®åã®ãµãåã§ãããã©ãããæ€èšŒããããšã¯ãæååãç¹å®ã®åœ¢åŒèšèªã«å«ãŸããŠãããã©ããããã§ãã¯ããããšãšèšç®äžåçã§ãã
ç¹ã«ãã¡ã€ã³æ€èšŒã¯ãTLD /ãããªãã¯ãµãã£ãã¯ã¹ã®æå¹æ§ããã§ãã¯ããå Žåãå®éã«ã¯ããªãè€éãªããšã§ãã RFCã«ãããžã§ããªãã¯ãã¡ã€ã³èªäœã¯ã /[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)+/
+æ倧255æåãšåããããåçŽã§ãããäžèšã®æ£èŠè¡šçŸã瀺ãããã«å®å
šãªæ£èŠææ³ã䜿çšããªãéããããã§ãå
¥åãéåžžã«è€éã§ãã @rozzzlyãŸãã¯ç§ã®ææ¡ããã®æååã®ã¿ã䜿çšããŠãããã°ã©ã ã§éåžžã«ç°¡åã«åãçæã§ããŸãïŒèªè
ã®æŒç¿ãšããŠæ®ããŠãããŸãïŒããæçµçµæã¯ãŸã ããªãè€éã§ãã
@isiahmeadows
ããã¯å€ããå°ãªããç§ã®ææ¡ã®æ¬è³ªã§ãããããã€ãã®å°ããªæ©èœãæ¬ ããŠããŸãã
ãã®ã¹ã¬ããå šäœãæåŸã«èªãã ã®ã¯1幎以äžåã®ããšã§ãã ç§ã¯äŒæ©äžã«éç¥ãèŠãŸããã @ rugkã®ã³ã¡ã³ããèªãã§ãã ãããæ¬è³ªçã«åã_ïŒ/éåžžã«é¡äŒŒããïŒ_ã¢ã€ãã¢ã«ã€ããŠãããªã詳现ãªææ¡ãææ¡ããŸããã
...äžèšã®æ£èŠè¡šçŸã瀺ãããã«ãå®å šãªæ£èŠææ³ã䜿çšããªãéããããã§ãå ¥åãéåžžã«è€éã«ãªããŸãã @rozzzlyãŸãã¯ç§ã®ææ¡ããã®æååã®ã¿ã䜿çšããŠãããã°ã©ã ã§éåžžã«ç°¡åã«åãçæã§ããŸãïŒèªè ã®æŒç¿ãšããŠæ®ããŠãããŸãïŒããæçµçµæã¯ãŸã ããªãè€éã§ãã
ç§ã®èãã§ã¯ãèš±å¯ããããšãææ¡ãããããªéå®ããããã¿ãŒã³ãããã³ã°ã®ããã®ããã€ãã®æ©èœã¯ãéåžžã«åçŽã§ã_å¿ ãããå³å¯ã§ã¯ãªã_ã¿ã€ãã³ã°ã«éåžžã«åœ¹ç«ã¡ãŸãã ç§ãæããäŸã¯æ£ç¢ºã«ã¯ã»ã©é ããã®ã§ãããã³ã³ãã€ã©ãŒãçç Žããããšã¯ãããŸããã
ãããã @ nikeeeãšããªãã®äž¡æ¹ãææããŠããããã«ãããã¯å±éºãªæ¥µç«¯ãªç¶æ³ã«@types/some-popular-project
ãžã®æŽæ°ãå
¬éãããã¹ãŠã®æ¥ãå°ç¡ãã«ããããšããŠããŸãã
type MixedCaseAlphaNumeric = (
| 'a'
| 'b'
| 'c'
// and so on
);
type StrWithLengthBeteen1And64<Charset extends string> = (
| `${Charset}`
| `${Charset}|${Charset}`
| `${Charset}|${Charset}|${Charset}`
// and so on
);
function updatePassword(userID: number, password: StrWithLengthBetween1And64<MixedCaseAlphaNumeric>): void {
// ...
}
ãããèŠéã«å ¥ãããšããã®çµåã¯èŠ³æž¬å¯èœãªå®å®ã®åå以äžã®ç°ãªãã¿ã€ãã
ä»ãç§ã¯ããã€ãã®éåžžã«é·ãå²ãåœãŠå¯èœæ§ãšã©ãŒãèŠãŠããŸãããããã®ããã®ïŒåãæšãŠãããŠããªãïŒãšã©ãŒãæ³åããŠãã ãã....
Type '"ð¢"' is not assignable to type '"a"|"b"|"c"..........."'.ts(2322)'
ãããã..ããã«ããã€ãã®åé¡ããããŸã
@rozzzlyãã®ã¿ã€ããTupleWithLengthBeteen1And64<Charset>
ãšïŒå®çŸå¯èœæ§ã®ç¹ã§ïŒç°ãªãçç±ã¯äœã§ããïŒ
ã³ã³ãã€ã©ãŒã¯ããã¹ãŠã®ã¿ã€ããæ£èŠåããã圢åŒã«å±éããããã«åŒ·å¶ãããããã§ã¯ãããŸãããå±éãããšãããªãéåžžã®ã¿ã€ãã§ããã«ççºããŸãã
ã3ãã1024ã®éã®æŽæ°ãïŒã¡ãã»ãŒãžãããã¡ã®å²ãåœãŠã®é·ããèããŠãã ããïŒã§ããç¯å²å€ãšèŠãªãããå ŽåãçŸæç¹ã§ã¯ãã®åé¡ã¯ã¿ã€ãã¹ã¯ãªããã§æå³ããããšã¯èšããŸããã
@simonbuchanä»ã«äœããªããšããŠããå°ãªããšããã¬ãã£ãã¯ã¹ãšãµãã£ãã¯ã¹ã®ã¿ã€ããååšããå¿ èŠããããŸãã ããèªäœãå€ãã®DOMã©ã€ãã©ãªãšãã¬ãŒã ã¯ãŒã¯ã«å¿ èŠã§ãã
ç§ã¯ããã殎æãããŠæ»ã«ãŸããããããŠããã€ãã®è¯ãææ¡ããã§ã«äžããããããšãç¥ã£ãŠããŸãã ããããç§ã¯ãäžéšã®äººãå°ãé¢çœããšæããããããªããã®ãè¿œå ãããã£ãã ãã§ãã
åŸæ¹åç §ã«çŽé¢ããŠãç§ã¯ããããŸã 決å®å¯èœã§ãããšæãããæªãã¯ãªãã«ããŠãææ°é¢æ°çã§ããå¯èœæ§ãé«ãã ãããããã ã®ç¥èã«åºã¥ããæšæž¬ã§ãã
éåç §ã«ãããæ£èŠè¡šçŸã¯æèèªç±ææ³ã®ã¹ãŒããŒã»ããã§ããæèäŸåææ³ãèšè¿°ã§ããŸãã ãããŠãCFGã®èšèªã®å¹³çã¯æ±ºå®äžå¯èœã§ãã ãããã£ãŠãç·åœ¢ææãªãŒãããã³ãšåçã®CSGã®å Žåã¯ããã«æªåããŸãã
DFAã«å€æã§ãããã¹ãŠã®æ£èŠè¡šçŸãæ£èŠè¡šçŸïŒé£çµãåéåãæãå ±ééšåãè£éåãªã©ïŒã§äœ¿çšãããŠãããšãããšãæ£èŠè¡šçŸãNFAã«å€æãããšOïŒnïŒã«ãªãã2ã®ç©ãåŸãããŸãã NFAã¯OïŒm * nïŒã§ãããåãå ¥ãç¶æ ã®çµæã®ã°ã©ãããã©ããŒã¹ãããšOïŒm * nïŒã«ãªããŸãã ãããã£ãŠã2ã€ã®æ£èŠè¡šçŸã®èšèªã®åçæ§/ãµãã»ããããã§ãã¯ããããšãOïŒm * nïŒã§ãã
åé¡ã¯ãããã§ã¯ã¢ã«ãã¡ããããæ¬åœã«å€§ããããšã§ãã æç§æžã¯ãDFA / NFA /æ£èŠè¡šçŸã«ã€ããŠè©±ããšããéåžžããµã€ãº1ã5ã®ã¢ã«ãã¡ãããã«å¶éãããŠããŸãã ããããJSæ£èŠè¡šçŸã䜿çšãããšãã¢ã«ãã¡ããããšããŠãã¹ãŠã®Unicodeã䜿çšã§ããŸãã 確ãã«ãã¹ããŒã¹é åããã®ä»ã®å·§åŠãªããã¯ãšçåŒ/ãµãã»ãããã¹ãã®æé©åã䜿çšããŠé·ç§»é¢æ°ãè¡šãå¹ççãªæ¹æ³ããããŸã...
å®æçãªå²ãåœãŠã®åãã§ãã¯ãããçšåºŠå¹ççã«è¡ãããšãã§ãããšç¢ºä¿¡ããŠããŸãã
次ã«ããã¹ãŠã®éæ£èŠå²ãåœãŠã§ãæ瀺çãªåã¢ãµãŒã·ã§ã³ãå¿ èŠã«ãªãå ŽåããããŸãã
ç§ã¯æè¿ãå°ããªæéãªãŒãããã³ãããžã§ã¯ãã«åãçµãã ã®ã§ãæ å ±ã¯ãŸã ç§ã®å¿ã®äžã§æ°é®®ã§ã= x
ç§ã誀解ããŠããªããã°ããã®ã¢ãããŒãã¯ç°¡åã«å·šå€§ãªã¿ã€ããäœæããããšãã§ããŸãã æ€èšïŒ
type TLD = 'com' | 'net' | 'org' | 'ly' | 'a' | 'b' | 'c' | 'd'; type Foo = `${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}${TLD}`; type Bar = `${Foo}${Foo}${Foo}${Foo}${Foo}`
ïŒããã¯ãå®è£ ãå ±çšäœåã䜿çšããããšãåæãšããŠããŸããå¥ã®/ããè€éãªå®è£ ã§æ©èœããå¯èœæ§ããããŸãïŒ
ããããªããšã«ãããã¯ãŸãã«æ°ãããã³ãã¬ãŒãæååãªãã©ã«ã¿ã€ãã§å¯èœãªããšã§ãã ãã®ã±ãŒã¹ã¯ãå ±çšäœã¿ã€ãã®ãããå€ãèšå®ããããšã§åé¿ã§ããããã§ãã
@AnyhowStep JS
ç·šéïŒç²ŸåºŠ
@rozzzlyããã®ãã®ã³ã¡ã³ããTS4.1.0ã§æ¯æ©åäœããããšã確èªããŸããïŒ
type TLD = 'com' | 'net' | 'org';
type Domain = `${string}.${TLD}`;
type Url = `${'http'|'https'}://${Domain}`;
const success: Url = 'https://example.com';
const fail: Url = 'example.com';
const domain: Domain = 'example.com';
éã³å Žã§è©ŠããŠã¿ãŠã fail
ã«ã³ã³ãã€ã«æãšã©ãŒãããããšã確èªããŠãã ããð€©
æŽæ°ïŒãã®æ©èœãå°ãè©ŠããåŸã¯ãå€ãã®ãŠãŒã¹ã±ãŒã¹ãã«ããŒããŸããã ããšãã°ã16é²ã«ã©ãŒæååã§ã¯æ©èœããŸããã
type HexChar = '0' | '1' | '2' | '3' | '4' | '5' | '6'| '7' | '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F';
type HexColor = `#${HexChar}${HexChar}${HexChar}${HexChar}${HexChar}${HexChar}`;
let color: HexColor = '#123456';
ä»æ¥ã§ã¯ã ãåŒã¯è€éãããŠè¡šçŸã§ããªãå ±çšäœåãçæããŸããïŒ2590ïŒãã§å€±æããŸã
@rozzzlyããã®ãã®ã³ã¡ã³ããTS4.1.0ã§æ¯æ©åäœããããšã確èªããŸããïŒ
type TLD = 'com' | 'net' | 'org'; type Domain = `${string}.${TLD}`; type Url = `${'http'|'https'}://${Domain}`; const success: Url = 'https://example.com'; const fail: Url = 'example.com'; const domain: Domain = 'example.com';
éã³å Žã§è©ŠããŠã¿ãŠã
fail
ã«ã³ã³ãã€ã«æãšã©ãŒãããããšã確èªããŠãã ããð€©
ããã¯ãã€ã³ããã¯ã¹ã«é©çšã§ããã°ãUXã©ã€ãã©ãªã§ç§ãã¡ã®ã»ãšãã©ãçŽé¢ããããŒã¿ãŸãã¯ã¢ãªã¢ã®åé¡ã解決ããŸãã
åºæ¬çã«ããã§ãããTSã§ã¯æååããèš±å¯ãããŠããªããããæããã«æ©èœããŸããã çªå·ã ããã¯æ¬è³ªçã«æååãªã®ã§ãæå¹ã«ã§ããŸããïŒ
https://www.typescriptlang.org/play?target=99&ts=4.1.0-dev.20201001#code/LAKALgngDgpgBAEQIZicgzgCzgXjgAwBIBvAcgBMUkBaUgXxPTACcBLAOwHM78BuUDmBjMAZkgDG8AJIAVGEzjFQcFXADalVBkwAFZgHsoALmRakWALpGmbLvxB1QocfvYL0AV3GT06I3Fl5MFxFCipqISZSI1JIsHpeIA
_Update_ïŒãã®æ©èœãå°ãè©ŠããåŸã¯ãå€ãã®ãŠãŒã¹ã±ãŒã¹ãã«ããŒããŸããã ããšãã°ã16é²ã«ã©ãŒæååã§ã¯æ©èœããŸããã
type HexChar = '0' | '1' | '2' | '3' | '4' | '5' | '6'| '7' | '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F'; type HexColor = `#${HexChar}${HexChar}${HexChar}${HexChar}${HexChar}${HexChar}`; let color: HexColor = '#123456';
ä»æ¥ã§ã¯ã ãåŒã¯è€éãããŠè¡šçŸã§ããªãå ±çšäœåãçæããŸããïŒ2590ïŒãã§å€±æããŸã
ãªãªãŒã¹ããŒãã«ã¯ããã®å¶éãžã®èšåãããã€ããããŸããã å¯èœãªãã¹ãŠã®æå¹ãªçµã¿åããã®ãªã¹ããäœæããŸãããã®å Žåã16,777,216ïŒã€ãŸãã16 ^ 6ïŒã®ã¡ã³ããŒã§çµåãäœæããŸãã
ããã¯çŽ æŽãããã¢ã€ãã¢ã§ã... Igmatã¯ã2016幎ã«ããšã«ããçŽã®äžã§èŠæ ãã®ããçŽ æŽãããæçš¿ãããã€ãäœæããŸããã
é¢æ°ã«æž¡ããããªããžã§ã¯ããªãã©ã«ã®ããŒãæå¹ãªcssã¯ã©ã¹åã§ããããšã確èªãããã£ãã®ã§ããããèŠã€ããŸããã å®è¡æã«ç°¡åã«ç¢ºèªã§ããŸã...ããããç¹ã«ãªããžã§ã¯ããªãã©ã«ãããŒãã³ãŒãã£ã³ã°ããŠããã ãã§ãtypescriptã次ã®ããšãç解ããå¿
èŠããªãç¶æ³ã§ã¯ãtypescriptãã³ã³ãã€ã«æã«ãããå®è¡ã§ããããšã¯æããã§ãã MyUnionExtendedExotic
å€åãã€ãç§ã¯ããçç£çãªè²¢ç®ãããã®ã«ååãªç¥èãããã§ãããïŒ/
@rozzzlyããã®ãã®ã³ã¡ã³ããTS4.1.0ã§æ¯æ©åäœããããšã確èªããŸããïŒ
ããã ç§ã¯æ£çŽãªãšãããå°ãªããšãããã«ã¯ããããå®è£ ãããããšãæåŸ ããŠããŸããã§ããã
@ chadlavi-å€äŸé
ãªãªãŒã¹ããŒãã«ã¯ããã®å¶éãžã®èšåãããã€ããããŸããã å¯èœãªãã¹ãŠã®æå¹ãªçµã¿åããã®ãªã¹ããäœæããŸãããã®å Žåã16,777,216ïŒã€ãŸãã16 ^ 6ïŒã®ã¡ã³ããŒã§çµåãäœæããŸãã
ããã©ãŒãã³ã¹ã®é¢ã§åé¡ã«ãªãåã«ããã®ãŠããªã³ãã©ãã ã倧ãããªãããç¥ããããšæããŸãã @styfleã®äŸã¯ããã®å€©äºã«ã¶ã€ããã®ãããã«ç°¡åãã瀺ããŠããŸãã æããã«ãè€éãªåã®æçšæ§ãšããã©ãŒãã³ã¹ã®åç©«éæžãããçšåºŠèŠèŸŒãŸããŸãã
@thehappycheese
é¢æ°ã«æž¡ããããªããžã§ã¯ããªãã©ã«ã®ããŒãæå¹ãªcssã¯ã©ã¹åã§ããããšã確èªãããã£ã
çŸåšã®å®è£
ã§ã¯äžå¯èœã ãšç§ã¯ããªãèªä¿¡ãæã£ãŠããŸãã æ°éè©ãšç¯å²ããµããŒããããŠããå Žåã¯ãããããBEMã¹ã¿ã€ã«ã®ã¯ã©ã¹åã®æ€èšŒãè¡ãããŸãã ãã®ããã®æšæºã®jsæ£èŠè¡šçŸã¯ãã²ã©ããã®ã§ã¯ãããŸããã
^\.[a-z]([a-z0-9-]+)?(__([a-z0-9]+-?)+)?(--([a-z0-9]+-?)+){0,2}$
ãŸããå®è£
ãçŸç¶ã§ã¯ãšã³ãããŒãšã³ãã®äžèŽã§ãããäœããªããããã¢ã³ã«ãŒãç Žæ£ããããã ^
ãš$
ãæ瀺ãããŸãã ããã¯ãæå¹ãªcssã»ã¬ã¯ã¿ãŒã®çããµãã»ããã«å¯Ÿããæ¯èŒçåçŽãªæ£èŠè¡šçŸã§ãã äŸïŒ ಠ_à²
ã¯æå¹ãªã¯ã©ã¹åã§ãã åè«ãããªããã
ããããªããã ç§ã¯ãããããªããã°ãªããŸããã§ããã
TypeScriptã§æ£èŠèšèªãå®è£ ããŸããã
ããæ£ç¢ºã«ã¯ãTS4.1ã䜿çšããŠåçŽãªæ±ºå®æ§æéãªãŒãããã³ãå®è£ ããŸãã
ã€ãŸããTSã«ãã¥ãŒãªã³ã°ãã·ã³ããã§ã«å®è£ ã§ããŸãã ãããã£ãŠãDFAãšPDAã¯ãããã«æ¯ã¹ãŠãç°¡åãã§ãã
ãããŠããã³ãã¬ãŒãæååã¯ããããã䜿ããããããŸãã
ã³ã¢ã¿ã€ãã¯å®éã«ã¯ã·ã³ãã«ã§ã30LOCæªæºã«åãŸããŸãã
type Head<StrT extends string> = StrT extends `${infer HeadT}${string}` ? HeadT : never;
type Tail<StrT extends string> = StrT extends `${string}${infer TailT}` ? TailT : never;
interface Dfa {
startState : string,
acceptStates : string,
transitions : Record<string, Record<string, string>>,
}
type AcceptsImpl<
DfaT extends Dfa,
StateT extends string,
InputT extends string
> =
InputT extends "" ?
(StateT extends DfaT["acceptStates"] ? true : false) :
AcceptsImpl<
DfaT,
DfaT["transitions"][StateT][Head<InputT>],
Tail<InputT>
>;
type Accepts<DfaT extends Dfa, InputT extends string> = AcceptsImpl<DfaT, DfaT["startState"], InputT>;
ããã¯é£ããéšåã§ãããªãŒãããã³ãæå®ããŠããŸãã
ãããã誰ããTypeScriptDFAâ¢ãžã§ãã¬ãŒã¿ãŒã«æ£èŠè¡šçŸãäœæã§ãããšç¢ºä¿¡ããŠããŸã...
ãŸãããé·ã6ã®16é²æååãã®äŸã§ã¯ãéãããã«ãŒã䜿çšããŠãé¢æ°ãã©ã¡ãŒã¿ãŒãæ£èŠè¡šçŸã«äžèŽããæååã®ã¿ãåãå ¥ããããã«ã§ããããšã瀺ããŠããŸãã
declare function takesOnlyHex<StrT extends string> (
hexString : Accepts<HexStringLen6, StrT> extends true ? StrT : {__err : `${StrT} is not a hex-string of length 6`}
) : void;
//OK
takesOnlyHex("DEADBE")
//Error: Argument of type 'string' is not assignable to parameter of type '{ __err: "DEADBEEF is not a hex-string of length 6"; }'.
takesOnlyHex("DEADBEEF")
//OK
takesOnlyHex("01A34B")
//Error: Argument of type 'string' is not assignable to parameter of type '{ __err: "01AZ4B is not a hex-string of length 6"; }'.
takesOnlyHex("01AZ4B")
ãããããŒãã¹ãã¬ã€ã°ã©ãŠã³ãã§ãã æ£èŠè¡šçŸ/^hello .*/
å®è£
ããŸã
ãããŠå¥ã®éã³å Ž; æ£èŠè¡šçŸ/ world$/
å®è£
ããŸã
æåŸã®äŸãšããŠã Playground ; ããã¯æµ®åå°æ°ç¹æååã®æ£èŠè¡šçŸã§ãïŒ
@AnyhowStepããŠãç§ã¯ããªãã®DFAã®ã¢ã€ãã¢ã䜿çšããŠãåçŽãªæ£èŠè¡šçŸ[abc]{4}
ãå®è£
ããŸãããããã¯ãæåabcãæ¬ èœããŠããããæ£ç¢ºã«4ã®é·ãã§ããããšãæå³ããŸãïŒaaaaãabccãbbccãªã©ïŒã
éã³å Ž
https://cyberzhg.github.io/toolbox/min_dfa?regex=ZCgoYmQqYiopKmMpKg==
https://github.com/CyberââZHG/toolbox
ãã£ãšæå¿åãããã°ãäžèšã®ãããªãã®ãã€ããã§ãæ£èŠè¡šçŸãTSDFAâ¢ã«å€ããããã«äœ¿çšããŸãç¬
ããŠãç§ã¯ãããã¿ã€ããäžç·ã«æããŸããã
https://glitch.com/~sassy-valiant-heath
[ç·šé] https://glitch.com/~efficacious-valley-repair <-ããã«ãããããè€éãªæ£èŠè¡šçŸã®åºåãå€§å¹ ã«åäžããŸãã
[ç·šé] Glitchã¯ãé·æé䜿çšãããŠããªãç¡æã®ãããžã§ã¯ããã¢ãŒã«ã€ãããããã§ãã ã ãããããã«ãã¡ã€ã«ãå«ãgitãªããžããªããããŸãã
https://github.com/AnyhowStep/efficacious-valley-repair/tree/main/app
ã¹ããã1ãããã«æ£èŠè¡šçŸãå
¥åããŸãã
ã¹ããã2ã[å€æ]ãã¯ãªãã¯ãã
ã¹ããã3ãçæãããTSãã¬ã€ã°ã©ãŠã³ãURLãã¯ãªãã¯ãã
ã¹ããã4ã InLanguage_0
ãŸã§äžã«ã¹ã¯ããŒã«ããŸãã
ã¹ããã5ãå
¥åå€ã§éãã§ã
https://www.npmjs.com/package/regex2dfaã®äœè ã§ãã@kpdyerã«ãå€æã®æéã®ãããäœæ¥ãå«ãã§ãã ããã
誰ããããå°ã匷åãªãã®ãå¿ èŠãšããå Žåã«åããŠãããã«ãã¥ãŒãªã³ã°ãã·ã³ããããŸãð
ãã®ã¹ã¬ããã¯é·ãããŠèªãããšãã§ãããã³ã¡ã³ãã®å€ãã¯ãã³ãã¬ãŒããªãã©ã«ã¿ã€ãã«ãã£ãŠå¯ŸåŠãããŠãããããããã¯ããå€ããŠããŸãã ãã®æ©èœã«ãã£ãŠæå¹ã«ãªãå¯èœæ§ã®ããæ®ãã®ãŠãŒã¹ã±ãŒã¹ã«ã€ããŠèª¬æããããã«ãæ°ããåé¡ïŒ41160ãäœæããŸããã ããã§åã·ã¹ãã ããŒãµãŒã«ã€ããŠåŒãç¶ãè°è«ããŠãã ããð
æãåèã«ãªãã³ã¡ã³ã
èšèšææ¡
ããéçºè ã¯ãã®åŸãåãªãæååããæå®ãããå€ãå¿ èŠãšãããšãäŸããããããããŸãããåçŽãªæååãªãã©ã«äŸãã°CSSã®è²ãé»åã¡ãŒã«ãé»è©±çªå·ãéµäŸ¿çªå·ãã®åéåãšããŠããããåæããããšã¯ã§ããŸããéæ©æ¡åŒµåãããªã©JSONã¹ããŒãä»æ§ã¯ãã©ã®äžè¬JSONãªããžã§ã¯ãã®ã¹ããŒããèšè¿°ããããã«äœ¿çšãããã®ã¯ãTSã¿ã€ãã·ã¹ãã ã®èŠ³ç¹ãã
regex-validated string type
ããã³regex-validated string type of index
ãšåŒã°ããå¯èœæ§ã®ããpatternããã³patternPropertiesãæã£ãŠããŸããç®æš
éçºè ã«ãJSONã¹ããŒãã«äžæ©è¿ãåã·ã¹ãã ãæäŸããŸããããã¯ãéçºè ãäžè¬çã«äœ¿çšããå¿ èŠã«å¿ããŠæååæ€èšŒãã§ãã¯ãå¿ããªãããã«ããŸãã
æ§æã®æŠèŠ
ãã®æ©èœã®å®è£ ã¯ã次ã®4ã€ã®éšåã§æ§æãããŠããŸãã
æ£èŠè¡šçŸã§æ€èšŒãããã¿ã€ã
æ£èŠè¡šçŸã§æ€èšŒãããå€æ°ã¿ã€ã
åãã§ãããããèªã¿ããã
æ£èŠè¡šçŸã§æ€èšŒãããå€æ°ã¿ã€ãã®ã€ã³ããã¯ã¹
åãã§ãããããèªã¿ããã
å¯å€åã®åã¬ãŒã
ãšåã
èªã¿ããããåäžãããããã«å®çŸ©ãããåã䜿çšãã
ãšåã
ã€ã³ããã¯ã¹ã¿ã€ãã®ã¿ã€ãgurard
ãšåã
èªã¿ããããåäžãããããã«å®çŸ©ãããåã䜿çšãã
ãšåã
ã»ãã³ãã£ãã¯ã®æŠèŠ
å²ãåœãŠ
æ®å¿µãªããããã®èšäºã«ããããã©ãŒãã³ã¹ãžã®å€§ããªåœ±é¿ãªãã«ãããæ£èŠè¡šçŸãå¥ã®æ£èŠè¡šçŸã®ãµãã¿ã€ãã§ãããã©ããã確èªããããšã¯ã§ããŸããã ãããã£ãŠãå¶éããå¿ èŠããããŸãã ãã ãã次ã®åé¿çããããŸãã
æ®å¿µãªããã
string
å€æ°ã®regex-validated
string
å€æ°ãžã®å²ãåœãŠãå¶éããå¿ èŠããããŸããããã¯ãã³ã³ãã€ã«æã«æ£èŠè¡šçŸãšäžèŽãããšããä¿èšŒããªãããã§ãããã ããããã«ç€ºãããã«ãæ瀺çãªãã£ã¹ãã¬ãŒããŸãã¯åã¬ãŒãã䜿çšã§ã
幞ããªããšã«ãæååãªãã©ã«ã®å Žåã¯ããã§ã¯ãããŸãããæååãªãã©ã«ã䜿çšããŠãããšãã«ããã®å€ãæ£èŠè¡šçŸãšäžèŽããããšã確èªã§ããããã§ãã
ã€ã³ããã¯ã¹ã®åçµã
ã€ã³ããã¯ã¹ã®
regex-validated type
ã®åçŽãªã±ãŒã¹ã«ã€ããŠã¯ãã€ã³ããã¯ã¹ã¿ã€ãã®ã¿ã€ãgurardãåç §ããŠãã ããããããããã£ãšè€éãªã±ãŒã¹ããããããããŸããïŒ
ãªãã©ã«ã«ã¯ãã®ãããªåé¡ã¯ãããŸããã
ãã ããå€æ°ã®å Žåã次ã®ããçŸå®çãªäŸã®ããã«ãã¿ã€ãã¬ãŒãã䜿çšããã®ãæåã®ãªãã·ã§ã³ã§ãã
ãããã
Gmail
åã«å¯ŸããŠããé©åãªå®çŸ©ã䜿çšãããšãå¥ã®åã®çµã蟌ã¿ãè¡ãããŸããåéåãšäº€å·®ç¹
å®éã«ã¯ãäžè¬çãªã¿ã€ããš
regex-validated
ã¿ã€ãã¯å®éã«ã¯ç°ãªããããcorrecltyããããã®åéåãšå ±ééšåãåŠçããæ¹æ³ã®ã«ãŒã«ãå¿ èŠã§ãããžã§ããªãã¯
ãžã§ããªãã¯ã«ã¯ç¹å¥ãªã±ãŒã¹ã¯ãªãã®ã§ã
regex-validated
åã¯ãéåžžã®åãšåãããã«ãžã§ããªãã¯ã§äœ¿çšã§ããŸãã以äžã®ãããªå¶çŽã®ãããžã§ããªãã¯ã¹ã®å Žåã
regex-validated
åã¯æååã®ããã«åäœããŸããæŸåºã®æŠèŠ
éåžžã®ã¿ã€ããšã¯ç°ãªãã
regex-validated
ã¯æŸåºã«ããããã®åœ±é¿ãåãŒããŸããã³ã³ãã€ã«ãããŸãïŒ
äºææ§ã®æŠèŠ
ãã®æ©èœã¯ããããå£ãå¯èœæ§ãããã±ãŒã¹ã®ã¿ãããã
regex-validated
ã¿ã€ããéåžžã®ã¿ã€ããšã¯ç°ãªã圱é¿ãäžããããšã«é¢é£ããŠãããããäºææ§ã«åé¡ã¯ãããŸããããããã£ãŠãããã¯æå¹ãªTSã³ãŒãã§ãã以äžã®ã³ãŒããããã§ãªãå ŽåïŒ
ãããã2çªç®ã¯ãã§ã«ç¡å¹ã§ããããå¥ã®çç±ïŒå宣èšãééã£ãŠããïŒãåå ã§ãã
ãããã£ãŠããã®åã
regex-validated
å Žåã«åããŠãåãšåãååã®å€æ°ã®å®£èšãå¶éããå¿ èŠããããŸããPS
ç§ãããããèŠéããããšãèªç±ã«ææããŠãã ããã ãã®ææ¡ãæ°ã«å ¥ã£ããããããã«ããŒãããã¹ããäœæããŠãPRãšããŠè¿œå ããŠã¿ãŠãã ããã