์์ฑ์ด ๋ฌธ์์ด(๋๋ ๋ฌธ์์ด ์งํฉ)์ผ ์๋ ์์ง๋ง ํจํด๊ณผ ์ผ์นํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
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 ํ๊ธฐ๋ฒ์ผ๋ก ์์ ๊ฐ์ ์ ์ฅํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ ๋๋ค.
์ด๋ป๊ฒ ์๊ฐํ๋์?
์, ๋๋ ์ด๊ฒ์ ํ์คํ Typed๋ฅผ ํตํด ๋น์งํ๋ ๊ฒ์ ๋ณด์์ต๋๋ค. ์๋น์ค ๊ณ์ธต์์ ์ด์ ๊ฐ์ ๊ฒ์
์ฃผ์ ๋ฌธ์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
"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๋ก ๊ฒ์ฆ๋ ๋ฌธ์์ด ์ ํ_๊ณผ ์ด๋ป๊ฒ ์๋ํฉ๋๊น?
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
๋ _regex๋ก ๊ฒ์ฆ๋ ๋ฌธ์์ด ์ ํ_์
๋๋ค.
ํธ์ง: ์ด ๋ฌธ์ ๋ ๋คํญ์ ์๊ฐ์ ํด๊ฒฐํ ์ ์๋ ๊ฒ ๊ฐ์ต๋๋ค( ์ ๊ท ํํ์์ ๋ํ ํฌํจ ๋ฌธ์ ์ฐธ์กฐ).
TypeStyle์๋ ๋์์ด ๋ฉ๋๋ค: https://github.com/typestyle/typestyle/issues/5 :rose:
JSX์์ @RyanCavanaugh ์ ์ ๋ ์ฌ๋๋ค์ด aria-
(๋ฐ ์ ์ฌ์ ์ผ๋ก data-
) ์์ฑ์ ์ถ๊ฐํ๋ ๊ฒ์ ๋ณด์์ต๋๋ค. ์ค์ ๋ก ๋๊ตฐ๊ฐ๊ฐ ์์ ํ์์ผ๋ก ConfirmTyped์ ๋ฌธ์์ด ์ธ๋ฑ์ค ์๋ช
์ ์ถ๊ฐํ์ต๋๋ค. ์ด์ ๋ํ ์๋ก์ด ์์ธ ์๋ช
์ด ๋์์ด ๋ ๊ฒ์
๋๋ค.
interface IntrinsicElements {
// ....
[attributeName: /aria-\w+/]: number | string | boolean;
}
๊ฐ๋ฐ์๊ฐ ๋ฌธ์์ด๋ณด๋ค ๋ ๋ง์ ์ง์ ๋ ๊ฐ์ด ํ์ํ์ง๋ง CSS ์์, ์ด๋ฉ์ผ, ์ ํ ๋ฒํธ, ZipCode, swagger ํ์ฅ ๋ฑ๊ณผ ๊ฐ์ ๋จ์ํ ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ ์กฐํฉ์ผ๋ก ์ด๊ฑฐํ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก json ์คํค๋ง ์ฌ์๋ JSON ๊ฐ์ฒด์ ์คํค๋ง๋ฅผ ์ค๋ช
ํ๋ ๋ฐ ์ฌ์ฉ๋๋ ํจํด ๋ฐ patternProperties ๋ TS ์ ํ ์์คํ
์ธก๋ฉด์์ regex-validated string type
๋ฐ regex-validated string type of index
๋ผ๊ณ ํ ์ ์์ต๋๋ค.
๊ฐ๋ฐ์๊ฐ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ 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
๋ณ์์ ํ ๋นํ๋ ๊ฒ๋ ์ ํ๋์ด์ผ ํฉ๋๋ค. ์ปดํ์ผ ์๊ฐ์ ์ ๊ท์๊ณผ ์ผ์นํ๋ค๋ ๋ณด์ฅ์ด ์๊ธฐ ๋๋ฌธ์
๋๋ค.
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
์ธ๋ฑ์ค์ ๊ฐ๋จํ ๊ฒฝ์ฐ๋ ์ธ๋ฑ์ค ์ ํ์ ๋ํ ์ ํ ๋ณดํธ๋ฅผ ์ฐธ์กฐํ์ญ์์ค.
๊ทธ๋ฌ๋ ๋ ๋ณต์กํ ๊ฒฝ์ฐ๊ฐ ์์ ์ ์์ต๋๋ค.
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
์ ํ์ ์ค์ ๋ก ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ํฉ์งํฉ๊ณผ ๊ต์ฐจ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋ ๊ท์น์ด ํ์ํฉ๋๋ค.
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
type์ ์ผ๋ฐ ํ์
๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ ๋ค๋ฆญ๊ณผ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค.
์๋์ ๊ฐ์ ์ ์ฝ ์กฐ๊ฑด์ด ์๋ ์ ๋ค๋ฆญ์ ๊ฒฝ์ฐ 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 = { ... };
๊ทธ๋ฌ๋ ๋ ๋ฒ์งธ๋ ์ด๋ฏธ ์ ํจํ์ง ์์ง๋ง ๋ค๋ฅธ ์ด์ ๋ก ์ธํด(์ ํ ์ ์ธ์ด ์๋ชป๋์์ต๋๋ค).
๋ฐ๋ผ์ ์ด์ ์ด ์ ํ์ด 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
๋ฐ๋ผ์ ์ ๊ท ํํ์์ด ์ ์ฝํ์ง ์๊ณ ๋ชจ๋ ์์น์์ ๋ณต์ฌ๋์ด์ผ ํ๋ฏ๋ก ์ฌ์ฉ์๊ฐ ์ฝ๊ฒ ์ค์ํ ์ ์๋ค๋ ์ ์ ์ ์ธํ๊ณ ๋ ๋ฐฉ์ถ์ ์ํฅ์ ๋ฏธ์น์ง ์๊ณ ๊ด์ฐฎ์ ๋ณด์
๋๋ค. ๊ทธ๋ฌ๋ ์ด ํน๋ณํ ๊ฒฝ์ฐ์๋ 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
emission์ ์ฝ๊ฐ ๋ณ๊ฒฝํด์ผ ํฉ๋๋ค.
@DanielRosenwasser , ์ด ์ ์์ ๋ํ ํผ๋๋ฐฑ์ ์ ๊ณตํด ์ฃผ์๊ฒ ์ต๋๊น? ๊ทธ๋ฆฌ๊ณ ๊ฐ๋ฅํ๋ค๋ฉด ์ฌ๊ธฐ์ ์ธ๊ธ๋ ํ
์คํธ์ ๋ํด์๋ ๋ง์ฐฌ๊ฐ์ง์
๋๊น?
๋ ์ ๋ง์ด ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๋์๋ง์ ์ํ์ง๋ง ๊ทธ๊ฒ์ ๋ง์ ์๊ฐ์ ํ์๋กํ๋ค ( tsc
์ ๋ง ํ๋ก์ ํธ๋ฅผ ๋ณต์กํ๊ณ ๋๋ ์ฌ์ ํ ๋ด๋ถ ์๋ ๋ฐฉ์์ ์ดํด์ ์ผํด์ผ) ๋๋ ์๊ณ ์๋คํ์ง ์์ต๋๋ค ์ด ์ ์์ ๊ตฌํํ ์ค๋น๊ฐ ๋์์ต๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ค๋ฅธ ์ธ์ด ๋์์ธ ๋น์ ์ด๋ ๋ค๋ฅธ ์ด์ ๋ก ์ธํด ์ด๋ฌํ ๋ฐฉ์์ผ๋ก ๊ตฌํ๋ ์ด ๊ธฐ๋ฅ์ ๊ฑฐ๋ถํ ๊ฒ์
๋๋ค.
Hey @Igmat , ์ฒ์์ ๋ฌผ์ด
์์ํ๊ธฐ ์ํด ๋๋ ์ฌ์ ํ ๋ฐฉ์ถํ๊ธฐ ์ํด ์ด๋ค ์ข ๋ฅ์ ๋ณ๊ฒฝ์ด ํ์ํ์ง ์ดํดํ์ง ๋ชปํ๋ฉฐ ์ ํ์ ๊ธฐ๋ฐ์ผ๋ก ํ ์ด๋ค ์ข ๋ฅ์ ๋ฐฉ์ถ๋ ํ์ฉ๋์ง ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ฌ๊ธฐ์์ ๋น๋ชฉํ๋ฅผ ํ์ธ
๋ด๊ฐ ์ ๊ธฐํ์ด์ผ ํ๋ ๋ ๋ค๋ฅธ ๋ฌธ์ ๋ ์ญ์ฐธ์กฐ๋ฅผ ์ฌ์ฉํ๋ ์ ๊ท์ ๋ฌธ์ ์ ๋๋ค. ๋ด ์ดํด(๋ฐ ๊ฒฝํ)๋ ์ ๊ท์์ ์ญ์ฐธ์กฐ๊ฐ ์ ๋ ฅ์ ์ง์์ ์ธ ์๊ฐ์ ํ ์คํธ๋ฅผ ์คํํ๋๋ก ๊ฐ์ ํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ฝ๋์ผ์ด์ค์ธ๊ฐ์? ์๋ง๋, ํ์ง๋ง ์ผ๋ฐ์ ์ผ๋ก ํผํ๊ณ ์ถ์ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ ํธ์ง๊ธฐ ์๋๋ฆฌ์ค์์ ์์น์์ ์ ํ ๊ฒ์ฌ์ ์ต์ํ์ ์๊ฐ์ด ์์๋์ด์ผ ํ๋ค๋ ์ ์ ๊ฐ์ํ ๋ ํนํ ์ค์ํฉ๋๋ค.
๋ ๋ค๋ฅธ ๋ฌธ์ ๋ TypeScript ์ปดํ์ผ๋ฌ๊ฐ ์คํ๋๋ ์์ง์ ์์กดํ๊ฑฐ๋ ์ด๋ฌํ ์์
์ ์คํํ๊ธฐ ์ํด ์ฌ์ฉ์ ์ง์ ์ ๊ท์ ์์ง์ ๋น๋ํด์ผ ํ๋ค๋ ๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด, TC39๋ .
๊ฐ ๊ฐํ๊ณผ ์ผ์นํ ์ ์๋๋ก ์๋ก์ด s
ํ๋๊ทธ๋ฅผ ํฌํจํ๋๋ก ์ด๋ํ๊ณ ์์ต๋๋ค. ESXXXX์ ์ด๋ฅผ ์ง์ํ๋ ์ด์ ๋ฐํ์ ๊ฐ์ ๋ถ์ผ์น๊ฐ ์์ ์ ์์ต๋๋ค.
@igmat - @DanielRosenwasser ์ ๋ง์
๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ๋ํ ๊ทธ๊ฒ์ ์ ์ฉํ๊ฒ ๋ง๋ค๊ธฐ ์ํด ๋ฌธ์์ด์์ ์ ๊ท์ ๊ฒ์ฆ ์ ํ์ผ๋ก ์ขํ๋ ๊ฒ์ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.
๋์ ๋ฌธ์์ด์์ ์ ๊ท์ ์ ํจ์ฑ ๊ฒ์ฌ ์ ํ์ผ๋ก ๋ฒ์๋ฅผ ์ขํ ๊ฒฝ์ฐ์๋ง ํด๋น๋ฉ๋๋ค. ์ด๊ฒ์ ๋งค์ฐ ๋ณต์กํด์ง๋๋ค. ์ด ๊ฐ๋จํ ๊ฒฝ์ฐ์๋:
function foo(bar: number) {
let baz: /prefix:\d+/ = 'prefix:' + number;
}
์ ํ์ด ์ผ์นํ๋์ง ํ์ ํ ์ ์์ต๋๋ค. ์ซ์๊ฐ ์์์ด๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ๊ทธ๋ฆฌ๊ณ ์ ๊ท์์ด ๋ ๋ณต์กํด์ง๋ฉด ์ ์ ๋ ๋ณต์กํด์ง๋๋ค. ์ฐ๋ฆฌ๊ฐ ์ด๊ฒ์ ์ ๋ง๋ก ์ํ๋ค๋ฉด ์๋ง๋ "type interpolation: 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 , ๋๋ Design Goals๋ฅผ ์ฃผ์ ๊น๊ฒ ์ฝ์๊ณ , ๋ด๊ฐ ๋น์ ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๋ค๋ฉด ๋ฌธ์ ๋ Non-goals#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
}
๋ณด์๋ค์ํผ ์ฝ๋๋ ๊ฑฐ์ ๋์ผํฉ๋๋ค. ์ ๊ท์์ ์ผ๋ฐ์ ์ธ ๊ฐ๋จํ ์ฌ์ฉ๋ฒ์
๋๋ค. ๊ทธ๋ฌ๋ ๋ ๋ฒ์งธ ๊ฒฝ์ฐ๋ ํจ์ฌ ๋ ํํ์ ์ด๊ณ ์ ๊ท์ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์๋ฏธํ๋ ๋ณ์์ ํ ๋นํ๊ธฐ ์ ์ ๋ฌธ์์ด์ ํ์ธํ๋ ๊ฒ์ ์๋ ๊ฒ๊ณผ ๊ฐ์ด ์ฌ์ฉ์๊ฐ ์ค์๋ก ์ค์ํ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค.
๋ ๋ฒ์งธ๋ ์ด๋ฌํ ์ ํ ์ถ์ ์์ด๋ ์ผ๋ฐ์ ์ผ๋ก ์ธ๋ฑ์ค์์ ์ ๊ท์ ์ ํจ์ฑ ๊ฒ์ฌ ์ ํ์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์
๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ด๋ฌํ ์ธ๋ฑ์ค ํ๋๋ ๋ฆฌํฐ๋ด๋ก ์ํํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ฐํ์์ ํ์ธํ ์ ์๋ ์ผ๋ถ ๋ณ์์ ํจ๊ป ์๋ํ๊ธฐ ๋๋ฌธ์
๋๋ค. .
@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 ์ข์ต๋๋ค. ์ด์ ๋ํ ์์ด๋์ด๊ฐ ํ๋ ๋ ์์ต๋๋ค. ๋ค์๊ณผ ๊ฐ์ ๊ตฌ๋ฌธ์ ์ด๋ป์ต๋๊น?
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 , ๋ ๋ฒ์งธ ๋ฌธ์ ์ ๋ํด - ๋ด ์ ์์์ ์ปดํ์ผ๋ฌ๋ ๋ฆฌํฐ๋ด์ ๋ํด์๋ง ์ ๊ท์์ ์คํํ๊ณ ๋๊ตฐ๊ฐ๊ฐ ๋ค์๊ณผ ๊ฐ์ด ํ ๊ฒ ๊ฐ์ง ์๊ธฐ ๋๋ฌธ์ ๊ทธ๋ฐ ์ผ์ด ์ผ์ด๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
let something: /some-regex-with-backreferences/ = `
long enough string to make regex.test significantly affect performance
`
์ด์จ๋ ์ฐ๋ฆฌ๋ ์ค์๊ฐ ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์น๊ธฐ ์ํด ๋ฆฌํฐ๋ด์ด ์ผ๋ง๋ ์ค๋ ์ง์๋์ด์ผ ํ๋์ง ํ ์คํธํ ์ ์๊ณ ์ฌ์ฉ์๊ฐ ์ผ๋ถ ํธ์ง๊ธฐ ์๋๋ฆฌ์ค์์ ์ด๋ฌํ ์ํฉ์ ์ง๋ฉดํ๋ ๋์ ํ์ธํ ์ ์๋ ๊ฒฝ์ฐ ์ฌ์ฉ์์๊ฒ ๊ฒฝ๊ณ ํ๋ ๋ช ๊ฐ์ง ๊ฒฝํ์ ๋ฐฉ๋ฒ์ ๋ง๋ค ์ ์์ง๋ง ๊ทธ๊ฐ ์ปดํ์ผํ ๋ ํ์ธํ ๊ฒ์ ๋๋ค. ํ๋ก์ ํธ. ๋๋ ๋ค๋ฅธ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์์ ์ ์์ต๋๋ค.
์ธ ๋ฒ์งธ ์ง๋ฌธ์ ๋ํด ๋ชจ๋ ๊ฒ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๋์ง ํ์คํ์ง ์์ง๋ง ๊ตฌํ์ด ๋ค๋ฅธ ๊ฒฝ์ฐ target
from tsconfig
์ ๋ฐ๋ผ ์ ๊ท์ ์์ง์ ์ ํํด์ผ ํ ๊ฒ ๊ฐ์ต๋๋ค. ์ข ๋ ์กฐ์ฌ๊ฐ ํ์ํฉ๋๋ค.
@DanielRosenwass ์ด๋ค ์๊ฐ์ด ์์ต๋๊น? ๐ ์ด๊ธฐ ์ ์๊ณผ ๋ง์ง๋ง ์ ์์ ๋ํด. ๋ ๋ฒ์งธ์ ๋ํด ๋ ์์ธํ ๊ฐ์๋ฅผ ์์ฑํด์ผ ํ ์ ์์ต๋๊น?
@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
๊ทธ๋ฌ๋ ๋๋ ์ด ๋ฉ์ปค๋์ฆ์ ๊ธฐ๋ณธํ์ ๋์ด ๊ธฐ๋ณธํ์ด ์๋ ์ ํ์ผ๋ก ํ์ฅํ๋ ๊ฒ์ด ๋๋ฌด ๋ง์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
ํ ๊ฐ์ง ์ ์ @DanielRosenwasser ๊ฐ ๋ค์ํ ์ ๊ท์ ์์ง ๊ตฌํ์ ๋ํด ์ ๊ธฐํ ๋ฌธ์ ๊ฐ
@zspitz ์ ๋งํด ๋ณด์ด์ง๋ง ์ ์๊ฐ์๋ ์ปดํ์ผ๋ฌ ์ฑ๋ฅ์ ๋๋ฌด ๋ง์ ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค. ๊ธฐ๋ฅ์ด ๊ท์น์ ์ํด ์ ํ๋์ง ์๊ณ TS๊ฐ ๋๋ฌด ๋ณต์กํ๊ฑฐ๋ ์ฌ์ฉํ ์ ์๋ ์ผ๋ถ ๋ฆฌ์์ค์ ์์กดํ๋ ์ผ๋ถ ํํ์์ ๊ณ์ฐํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ปดํ์ผ ์๊ฐ์.
@์ด๊ทธ๋งํธ
๊ธฐ๋ฅ์ด ์ด๋ค ๊ท์น์ ์ํด ์ ํ๋์ง ์๊ธฐ ๋๋ฌธ์
์ผ๋์ ๋ ๋ช ๊ฐ์ง ๊ตฌ์ฒด์ ์ธ ์๊ฐ ์์ต๋๊น? ์๋ง๋ ์ ํจ์ฑ ๊ฒ์ฌ ๊ตฌ๋ฌธ์ 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 ๋ฐ ์น ๊ฐ๋ฐ์ ํ๋๋ฅผ ๋ฐ๊ฟ ๊ฒ์ ๋๋ค. ํ์ฌ ๊ตฌํ์ ๋ง๊ณ ์๋ ๊ฒ์ ๋ฌด์์ ๋๊น?
ํ์ฅ์ฑ๊ณผ ์ ํ ๋ฐฉ์ถ์ด ๋๋จธ์ง ๊ธฐ๋ฅ์ ๋ฐฉํดํด์๋ ์ ๋๋ค๋ ๋ฐ ๋์ํฉ๋๋ค. ์ด๋ฌํ ์ธก๋ฉด์ ๋ํ ๋ช ํํ ๊ฒฝ๋ก๊ฐ ์์ผ๋ฉด ๋์ค์ ์์ ๋ ๊ตฌํํ์ธ์.
๋ฌธ์์ด์ด ์๋ UUID ์ ํ์ ์ฐพ๊ณ ์ ์ฌ๊ธฐ์ ๋์ฐฉํ์ต๋๋ค. ๋ฐ๋ผ์ ์ด ๊ฒฝ์ฐ ๋ฌธ์์ด์ ์ ์ํ๋ ์ ๊ท์์ ๊ฐ๋ ๊ฒ์ด ๊ต์ฅํ ๊ฒ์ ๋๋ค. + ์ ํ์ ์ ํจ์ฑ์ ํ์ธํ๋ ๋ฐฉ๋ฒ(Email.test ์์ )๋ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
@skbergam ๋ค์ ํ๋ฒ ์ง์ ๊ตฌํํด๋ณด๋ ค๊ณ ํฉ๋๋ค. ํ์ง๋ง TS ํ๋ก์ ํธ๋ ์ ๋ง ๊ฑฐ๋ํ๊ณ ์ ๋ ์์ ์ด ์์ด์ ์งํ์ด ๊ฑฐ์ ์์ต๋๋ค. ๋๊ตฐ๊ฐ TS ํ์ฅ์ ๋ํ ๋ ๋ง์ ๊ฒฝํ์ด ์๋ค๋ฉด ๋์์ ์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค...
๋ ๊ฐ์ ๋์ผํ์ง ์์ ์ ๊ท ํํ์ ๊ฐ์ ํ์ ์ ํ/ํ ๋น ๊ฐ๋ฅ์ฑ ๊ด๊ณ๋ฅผ ์ค์ ํ ์ ์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ด ๋ช ๋ชฉ ์ ํ์ ํจ๊ณผ์ ์ผ๋ก ์์ฑํ๋ค๋ ์ ์ ํฅ๋ฏธ๋กญ์ต๋๋ค.
@RyanCavanaugh ์ด์ ์ @maiermic์ด ๋๊ธ์ ๋ฌ์์ต๋๋ค.
ํธ์ง: ์ด ๋ฌธ์ ๋ ๋คํญ์ ์๊ฐ์ ํด๊ฒฐํ ์ ์๋ ๊ฒ ๊ฐ์ต๋๋ค(์ ๊ท ํํ์์ ๋ํ ํฌํจ ๋ฌธ์ ์ฐธ์กฐ).
๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ผ๋ก ์ถฉ๋ถํ์ง ์์ ์ ์์ต๋๊น? ์ ๊ท ํํ์ ๊ด๊ณ๊ฐ ๋ง์ง ์๊ธฐ๋ฅผ ํฌ๋งํ์ง๋ง ๊ฒฐ์ฝ ์ ์ ์์ต๋๋ค.
์ ํ ๊ฒ์ฌ์ ๊ด๋ จํ์ฌ ์ ๊ท ํํ์ ๋ณต์ ๊ฐ ๋ง์์ ๋ค์ง ์๊ณ typeof
a const๊ฐ ์ถฉ๋ถํ์ง ์์ ๊ฒฝ์ฐ(์: .d.ts ํ์ผ) TS๋ valueof e
์ ๋ํด ์ด๋ป๊ฒ ์๊ฐํฉ๋๊น? e
iff e
์ ๋ฆฌํฐ๋ด ๊ฐ์ ๋ฆฌํฐ๋ด์ด๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ์ค๋ฅ์
๋๋ค( undefined
์ ๊ฐ์ ๊ฒ์ ๋ด๋ณด๋)?
@maxlk ๋ํ ์ฃผ์ ์์ ๋ฒ์ด /^((dog|cat|fish)(,(?=\b)|$))+$/
with test https://regex101.com/r/AuyP3g/1. ์ด๊ฒ์ ์ผํ ๋ค์ ๋จ์ด ๋ฌธ์์ ๋ํด ๊ธ์ ์ ์ธ lookahead๋ฅผ ์ฌ์ฉํ์ฌ DRY ๋ฐฉ์์ผ๋ก ์ฌ์ ์ ๊ฐ์ ๋ก ์ฌ๊ฒ์ฆํฉ๋๋ค.
์๋
ํ์ธ์!
์ด ์ํ๋ ์ด๋ป์ต๋๊น?
๊ฐ๊น์ด ์์ผ ๋ด์ ์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ ์์ ์
๋๊น? ๋ก๋๋งต์์ ์ด์ ๋ํ ๋ด์ฉ์ ์ฐพ์ ์ ์์ต๋๋ค.
@lgmat lib.d.ts
์์ ์ฌ์ฉ ๊ฐ๋ฅํ ์ ์๋ง ์ฌ์ฉํ์ฌ ๊ตฌ๋ฌธ์ ํ ์ค ํ์ดํ ํจ์๋ก ์ ํํ๋ ๊ฒ์ ์ด๋ป์ต๋๊น?
๊ทธ ๋๋ผ์ด ๊ฐ์ ์ฌํญ์ ์ฌ์ฉํ ์ ์์ต๋๊น? ์ ์ด๋ ์ํ ๋ฆด๋ฆฌ์ค์์๋?
์ ๊ท์ ์ ํจ์ฑ ๊ฒ์ฌ ์ ํ์ ํ ์คํธ ์์ฑ์ ์ ํฉํ๋ฉฐ ํ๋ ์ฝ๋ฉ๋ ์ ๋ ฅ์ ์ ํจ์ฑ ๊ฒ์ฌ๋ ์ข์ต๋๋ค.
+1. ์ฐ๋ฆฌ์ ์ฌ์ฉ ์ฌ๋ก๋ ๋งค์ฐ ์ผ๋ฐ์ ์ด๋ฉฐ 'dd/mm/YYYY'์ ๊ฐ์ ๋ฌธ์์ด ๋ ์ง ํ์์ด ํ์ํฉ๋๋ค.
์ ์๋ ๋๋ก ๋งค์ฐ ๋ฉ์ง ๊ธฐ๋ฅ์ด ๋ ์ ์์ง๋ง ์ ์ฌ๋ ฅ์ด ๋ถ์กฑํฉ๋๋ค.
๋ ๋์ ๋ฐฉ๋ฒ์ #21861์์ ์ ์ํ ๊ฒ์ฒ๋ผ ๊ตฌ๋ฌธ ๋ถ์์ ์์์์ฑํ๊ณ ํ๋ฌ๊ทธ์ธ์ผ๋ก ๋ด๋ณด๋ด๋ ๊ฒ์ ๋๋ค. ์ด ๋ฐฉ๋ฒ์ ์์ ๋ชจ๋ ๊ฒ์ด ๋ ๊ฐํ๋ฅธ ํ์ต ๊ณก์ ์ ๋๊ฐ๋ก ๋ฌธ์ ๊ฐ ๋์ง ์์ง๋ง ์ด๋ด! regexp ๊ฒ์ฌ๋ ๊ทธ ์์ ๊ตฌํ๋์ด ์๋ ์ ์์ด ์ฌ์ ํ ์ ์ง๋๊ณ ๋ ๊ณ ๊ธ ๊ธฐ๊ณ์์ ๋์ฌ ์ ์์ต๋๋ค.
๋ด๊ฐ ๋งํ๋ฏ์ด ๋ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ ๋ฆฌํฐ๋ด์ ๋ํ ์ฌ์ฉ์ ์ง์ ๊ตฌ๋ฌธ ๊ณต๊ธ์์ ๋๋ค. #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
์์ ์ฌ์ฉ ๊ฐ๋ฅํ ์ ์๋ง ์ฌ์ฉํ์ฌ ๊ตฌ๋ฌธ์ ํ ์ค ํ์ดํ ํจ์๋ก ์ ํํ๋ ๊ฒ์ ์ด๋ป์ต๋๊น?
@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
๊ทธ๋ฌ๋ ๋๋ ์ด ๋ฉ์ปค๋์ฆ์ ๊ธฐ๋ณธํ์ ๋์ด ๊ธฐ๋ณธํ์ด ์๋ ์ ํ์ผ๋ก ํ์ฅํ๋ ๊ฒ์ด ๋๋ฌด ๋ง์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๋ด๊ฐ ๋ณผ ์ ์๋ ์ฃผ์ ๋ฌธ์ ๋ ๋ณด์ ๋ฌธ์ ์ ๋๋ค. ์ผ๋ถ ์ ์ฑ ์ฝ๋๋ ์ ํ์ ํ์ธํ๋ ๋์ ๋ฒํผ๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ์ ธ์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ด๊ฒ๊ณผ ๊ด๋ จํ์ฌ ๋ง์ ์๋๋ฐ์ฑ์ ๊ตฌํํด์ผ ํฉ๋๋ค. ์ฐจ๋ผ๋ฆฌ ๋ฌธ์์ด๊ณผ ์ซ์์ ๋ํ ๋ ๊ฐ์ง ์๋ฃจ์ ์ ๋ณด๊ณ ์ถ์ต๋๋ค.
RegExp๋ ์ด๋ฅผ ์ ์์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ ์ ์ผํ ๋ฐฉ๋ฒ์ ์ญ์ถ์ ํํ์ ์ ๋ง๋๋
ํ ๊ฐ์ง ์ ์ @DanielRosenwasser ๊ฐ ๋ค์ํ ์ ๊ท์ ์์ง ๊ตฌํ์ ๋ํด ์ ๊ธฐํ ๋ฌธ์ ๊ฐ
๊ทธ๊ฒ์ ์ฌ์ค์ ๋๋ค. ์ด๊ฒ์ ์ข์ง ์์ง๋ง ์ฝ๋๋ฒ ์ด์ค์ ํ์ํ regExp์ "ํ๋์ ์ธ" ๋ถ๋ถ์ ์ง์ ํ์ฌ ํด๊ฒฐํ ์ ์์ต๋๋ค. ๋ชจ๋ ๋ ธ๋ ์์ ์๋ํ๋ ์ผ๋ฐ(ES3์ ๋๊น?) regexp๋ก ๊ธฐ๋ณธ ์ค์ ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์๋ก์ด ํ๋๊ทธ์ lookbehind ์ด์ค์ ์ ํ์ฑํํ๋ ์ต์ ์ด ์์ต๋๋ค.
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๋ ๊ณ ๊ธ RegExp๋ฅผ ํ๊ฐํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง, ๊ณ ๊ธ RegExp ๊ฒ์ฌ๋ฅผ ํ์ฑํํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํ๋ ๊ฒฝ๊ณ ๋ฅผ ์ ๊ณตํด์ผ ํ๋ค๊ณ ์ ์ํฉ๋๋ค.
์ฌ์ฉ์๊ฐ ๊ณ ๊ธ ํ๋๊ทธ๋ก ํ๋๊ทธ๋ฅผ ํ์ฑํ ํ๊ณ ๊ทธ์ ๋ ธ๋๊ฐ ์ด๋ฅผ ์ง์ํ๋ ๊ฒฝ์ฐ.
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๊ฐ ์ด๋ ๊ฒ ์์ฒญ๋ ์ ์ฌ๋ ฅ๊ณผ ์์ญ ๊ฐ์ง์ ๋ฉ์ง ์ ์์ ๊ฐ์ง๊ณ ์๋ค๋ ์ฌ์ค์ด ์ฐธ์ผ๋ก ์ํ๊น์ต๋๋ค.
AFAIK์ ์๋ ์ ์ ์ ํ์ํ์ง ์๊ณ ์ค์ ๋ก ํ์ํ์ง ์์ Emit ๊ฐ์ ๋ฅผ ์ ์ธํ๊ณ ๋ ์ข์์ผ๋ฏ๋ก ์ ์์ ์ฐจ๋จํด์๋ ์ ๋ฉ๋๋ค.
ํด๊ฒฐํ๋ ค๋ ๋ฌธ์ ๋ ์ ๊ท์ ๋ฆฌํฐ๋ด(๋ฌธ์์ด ๋ฐ ์ซ์ ๋ฆฌํฐ๋ด๊ณผ ํจ๊ณผ์ ์ผ๋ก ๋์ผํ๋ฏ๋ก ์ด๋ ต์ง ์์์ผ ํจ)๊ณผ ์ ํ ์ฐ์ฐ์ patternof
( typeof
์ ์ ์ฌ)์ ๋์
์ผ๋ก ํด๊ฒฐํ ์ ์์ต๋๋ค keyof
), ์ ๊ท์ ๋ฆฌํฐ๋ด ์ ํ์ ์ฌ์ฉํ๊ณ _validated string_ ์ ํ์ ๋ฐํํฉ๋๋ค. ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
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 ์ด๊ธฐ ์ ์์ ํ ๋ ์ถ๊ฐ ์ ํ ์ฐ์ฐ์๋ก ์ด๋ฌํ ์๋ฃจ์ ์ ๋ํด ์๊ฐํ์ง ์์์ต๋๋ค.
์ ํ์ ์ํด ๋ฐ์ํ๋ ๋ฐฉ์ถ ์ํฅ์ ์ ๊ฑฐํ๋ ์ด ์ ๊ทผ ๋ฐฉ์์ด ๋ ์ฅํฉํด ๋ณด์ด์ง๋ง ์ข์ํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ ์๋ก์ด ํค์๋ ์ถ๊ฐ๋ฅผ ๊ฑด๋๋ฐ๊ธฐ ์ํด ์ด ์ ์์ ํ์ฅํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํ๊ฒ ํฉ๋๋ค.
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`
}
@์ด๊ทธ๋งท ์ฟจ. ๊ทํ์ ์ ์์ TypeScript์ ๋ํด ๋ ์์ฐ์ค๋ฝ๊ฒ ๋๊ปด์ง๊ณ ์ปดํ์ผ๋ฌ์ ๋ํ ๋ณ๊ฒฝ์ด ๋ ํ์ํฉ๋๋ค. ์ด๋ ์๋ง๋ ์ข์ ์ผ์ ๋๋ค. ๋ด ์ ์์ ์ ์ผํ ์ฅ์ ์ ์ ๊ท์ ๋ฆฌํฐ๋ด์ด ๋ฌธ์์ด ๋ฐ ์ซ์ ๋ฆฌํฐ๋ด๊ณผ ๋์ผํ๊ฒ ๋๊ปด์ง ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ด๋ ์ผ๋ถ ์ฌ๋๋ค์๊ฒ ํผ๋์ ์ค ์ ์์ต๋๋ค.
let a: 'foo' = 'foo'; // works
let b: 42 = 42; // works
let c: /x/ = /x/; // error
๊ทธ๋ฌ๋ ๋๋ ๋น์ ์ ์ ์์ ๋จ์ํจ์ด ๋จ์ ์ ๋ฅ๊ฐํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํธ์ง: ๋๋ ValidatedStringType<R>
์ ๊ธธ์ด๊ฐ ์ ๋ง ๋ง์์ ๋ค์ง ์์ต๋๋ค. ๊ฒ์ฆ๋ ๋ฌธ์์ด ํจํด ์ ํธ์ถํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค๋ฉด ๊ฒฐ๊ตญ PatternOf<R>
์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ทํ์ ์ ํ์ด ์
๋ ฅํ๋ ๋ฐ ์๊ฐ์ด ๋ ์ค๋ ๊ฑธ๋ฆฐ๋ค๋ ๋ง์ ์๋๋๋ค. ๋๋ถ๋ถ์ ์ฌ๋๋ค์ ์ฒ์ ์ธ ๊ธ์๋ฅผ ์
๋ ฅํ๊ณ ํญ์ ๋๋ฅด๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ๋จ์ง ๋ ํฐ ์ฝ๋ ์คํ๊ฒํฐ์ผ์ด์
์ํฅ์ด ์์ ๋ฟ์
๋๋ค.
@Igmat ๋น์ ์ ์๋ฃจ์ ์ ๊ฐ๋ฐ ์์ ์์ ํ๋ฅญํ์ง๋ง ๊ฐ๋ ์ฑ์ด ์ฌ๋ผ๊ฐ์๋ก @m93a๊ฐ ์ ์ํ ๊ฐ๋ฅ์ฑ์ด ํจ์ฌ ๋ ๋์ ๊ฒ์ ๋๋ค. ๋ด๋ถ์ ์ผ๋ก๋ ๊ฑฐ์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ํํํ ์ ์๋ค๊ณ ์๊ฐํ์ง๋ง ์ต๋ํ ๊ฐ๋จํ๊ฒ ์ฌ์ฉ์์๊ฒ ์ ์ํด์ผ ํฉ๋๋ค.
@Akxe ์ ๋ ๊ฐ๋ฐ์๊ฐ ๋งค์ฐ ๊ตฌ์ฒด์ ์ธ ์ฌ์ฉ ์ฌ๋ก๊ฐ ํ๋๋ง ์๋ ๋ค๋ฅธ ํค์๋๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ์ข์ํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
@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์ ์ถฉ๋ํฉ๋๋ค. ์ด์ ํ์์ ์์์ ํํ์์ด ์๋ ์ผ๋ฐ ์ธ์๋ก๋ง ์ ๋ฌํ ์ ์์ต๋๋ค. ์ ์ํ ๊ตฌ๋ฌธ์ ๋งค์ฐ ํผ๋์ค๋ฌ์ธ ๊ฒ์ ๋๋ค.
ํ์์ ์ทจํ๊ณ ํ์์ ๋ฐํํ๋ ํจ์์ธ ๊ฒ์ฒ๋ผ ์ ๋ค๋ฆญ ํ์์ ์๊ฐํ์ญ์์ค. ๋ค์ ๋ ์ฝ๋ ์กฐ๊ฐ์ ์๋ฏธ์ ๊ตฌ๋ฌธ ๋ชจ๋์์ ๋งค์ฐ ๊ฐ๊น์ต๋๋ค.
function foo(str: string) {
return str === 'bar' ? true : false
}
type foo<T extends string> = T extends 'bar' ? true : false;
์ ๊ตฌ๋ฌธ์ JavaScript์ ์ ๊ท์์ด let all = String(.*)
๋ก ์์ฑ๋์ด์ผ ํ๋ค๊ณ ์ ์ํ๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค. ์ด๋ ํจ์ ํธ์ถ ๊ตฌ๋ฌธ์ ๋ชป์ฐ๊ฒ ๋จ์ฉํ๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก ๋๋ ๋น์ ์ ์ ์์ด ๋ณ๋ก ์๋ฏธ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
@ m93a ๋ด ์ ์์ ์๋ฐ ์คํฌ๋ฆฝํธ๊ฐ ์๋ ์ ํ ์ฃผ์์ ๋ํ ๊ฒ์ ๋๋ค.
๋ด ๋จธ๋ฆฌ ๊ผญ๋๊ธฐ์์ @Igmat ,
interface RegExp {
test(stringToTest: string): stringToTest is string<this>;
}
@amir-arad, ์ฃ์กํฉ๋๋ค. ๊ทํ์ ์ ์์ ๋ ๊ท์คํ ์ธ๋ถ ์ ๋ณด๋ฅผ ์ถ๊ฐํ ์๋ ์์ง๋ง string
๋ ๋งค์ฐ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋ณธ ์์์ด๊ธฐ ๋๋ฌธ์ ์ธ๋ป ๋ณด๊ธฐ์๋ ์ ์ฒด TS ์ปดํ์ผ๋ฌ์ ๋ํ ๋งค์ฐ ์ค์ํ ๋ณ๊ฒฝ์ฒ๋ผ ๋ณด์
๋๋ค.
๋ช
๋ฐฑํ ๋ฌธ์ ๊ฐ ๋ณด์ด์ง๋ ์์ง๋ง ๊ทธ๋ฌํ ์ ์์ ํจ์ฌ ๋ ์์ธํ๊ณ ๊ธฐ์กด์ ๋ง์ ์๋๋ฆฌ์ค์ ๋ชฉ์ ์ ๋ํ ์ ์ ํ ์ ๋น์ฑ์ ํฌํจํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋น์ ์ ์ ์์ ํ๋์ ์ ํ์ ์ถ๊ฐํ๊ณ ํ๋์ ๊ธฐ๋ณธ ์ ํ์ ๋ณ๊ฒฝํ๋ ๋ฐ๋ฉด ๋ด ์ ์์ ํ๋์ ์ ํ๋ง ์ถ๊ฐํฉ๋๋ค.
๋ถํํ๋ ์ ๋ ๊ทธ๋ฌํ ๊ธฐ๋ฅ์ ๋ํ ์ ์์ ์์ฑํ๋ ๋ฐ ๋ง์ ์๊ฐ์ ํ ์ ํ ์ค๋น๊ฐ ๋์ง ์์์ต๋๋ค(๋ํ TS์ ๋ชจ๋ ์ ์์ด ์๋นํ ์ง์ฐ ์์ด ๊ตฌํ๋์ง๋ ์์๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค). ํ์ํ ๊ฒฝ์ฐ ๋ด ํผ๋๋ฐฑ์ ๊ธฐ๊บผ์ด ์ ๊ณตํ๊ฒ ์ต๋๋ค.
์ด๋ฌํ regexp ์ ํ์ด ์ค์ ์ ๊ท์(์ ๊ท๊ฐ ์๋ Perl๊ณผ ๊ฐ์ ์ ๊ท์์ด ์๋)์ธ ๊ฒฝ์ฐ ์ด๋ฅผ ๊ฒฐ์ ๋ก ์ FSM์ผ๋ก ๋ณํํ๊ณ ์ฌ๊ธฐ์ ๋ํด ๋ฐ์นด๋ฅดํธ ๊ณฑ ๊ตฌ์ฑ์ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๊ฒฐํฉ ๋ฐ ๋ถ๋ฆฌ๋ฅผ ์ป์ ์ ์์ต๋๋ค. ์ ๊ท์์ ๋ถ์ธ ์ฐ์ฐ์์ ๋ซํ๋๋ค.
๋ํ ๋ฌธ์์ด ๋ฆฌํฐ๋ด ์ ํ์ด ์์์ ์ด์ง ์๊ณ ์ปดํ์ผ ํ์ ๋ฌธ์ ๋ชฉ๋ก์ผ๋ก ํ์๋๋ ๊ฒฝ์ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ชจ๋ ์ฐ์ฐ์๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค. ์ฑ๋ฅ์ด ์ฝ๊ฐ ์ ํ๋ ๋ฟ์ ๋๋ค.
ํธ์ง: ์ค์๋ฅผ ์์ ํฉ๋๋ค.
Mithril์ด ์ด๊ฒ๋ค์ ์ค์ ๋ก ์ฌ์ฉํ ์ ์๋ค๋ ์ ์ ์ฃผ๋ชฉํ๊ธฐ ์ํด ๋ค๋ฅด๋ฉด, ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ์ Type-safe๊ฐ ๊ทธ๊ฒ ์์ด๋ ๊ฑฐ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค. ์ด๊ฒ์ ํ์ดํผ์คํฌ๋ฆฝํธ์ JSX ๊ตฌ๋ฌธ ๋ชจ๋์ ๊ฒฝ์ฐ์ ๋๋ค. (์ฐ๋ฆฌ๋ ๋ ๋ค ์ง์ํฉ๋๋ค.)
oninit
, oncreate
, onbeforeupdate
, onupdate
, onbeforeremove
๋ฐ onremove
์๋ ๊ณ ์ ํ ํํฌ๊ฐ ์์ต๋๋ค. ํน๋ณํ ํ๋กํ ํ์
.on
์์ํ๋ ๋ค๋ฅธ ๋ชจ๋ ๊ฒ์ด๋ฉฐ, ์ฐ๋ฆฌ๋ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ํจ์์ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๊ฐ์ฒด( handleEvent
๋ฉ์๋ ์ฌ์ฉ)๋ฅผ ๋ชจ๋ ์ง์ํ๋ฉฐ addEventListener
removeEventListener
.๋ฐ๋ผ์ ์ ๊ท์์ผ๋ก ๊ฒ์ฆ๋ ๋ฌธ์์ด ์ ํ + ์ ํ ๋ถ์ ์ ์ฌ์ฉ ํ์ฌ DOM vnode์ ๋ํด ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
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}`
- ์ด๊ฒ์ regexp /^value/
์ ๊ธฐ๋ฅ์ ์ผ๋ก ๋์ผํ์ง๋ง "value"
, "valuea"
๋ฐ "valueakjsfbf aflksfief fskdf d"
๋ชจ๋ ํ ๋น ๊ฐ๋ฅํฉ๋๋ค.`foo${string}bar`
- ์ด๊ฒ์ regexp /^foo.*bar$/
์ ๊ธฐ๋ฅ์ ์ผ๋ก ๋์ผํ์ง๋ง ์ ๊ทํํ๊ธฐ๊ฐ ์กฐ๊ธ ๋ ์ฝ์ต๋๋ค.`foo${string}bar${string}baz`
์ ์ ํจํ ํ
ํ๋ฆฟ ๋ฆฌํฐ๋ด ์ ํ์
๋๋ค.string
ํ์ฅ ํด์ผ ํ๋ฉฐ ์ฌ๊ท์ ์ด์ด์๋ ์ ๋ฉ๋๋ค. (๋ ๋ฒ์งธ ์กฐ๊ฑด์ ๊ธฐ์ ์ ์ธ ์ด์ ์
๋๋ค.)A
์
๋ ฅํ๋ ๋ฌธ์ ํ
ํ๋ฆฟ์ ํ ๋น ํ B
๋ฌธ์์ด์ ์งํฉ์ ํ ๋น ํ ๊ฒฝ์ฐ ๋ง A
์คํธ๋ง์ ์ธํธ์ ์๋ธ ์ธํธ์ ํ ๋น ํ B
.์์ ์ถ๊ฐํ์ฌ T
๋ ๋จ์ผ ๋ฌธ์ ๋ฌธ์์ด ๋ฆฌํฐ๋ด ์ ํ์ผ๋ก๋ง ๊ตฌ์ฑ๋์ด์ผ ํ๋ ํน์ starof T
์ ํ์ด ์กด์ฌํฉ๋๋ค. string
๋ starof (...)
์ ์ ํ ๋ณ์นญ์ผ๋ก ์กด์ฌํฉ๋๋ค. ์ฌ๊ธฐ์ ...
๋ lone์ ํฌํจํ์ฌ U+0000์์ U+FFFF๊น์ง์ ๋ชจ๋ ๋จ์ผ UCS-2 ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ ํฉ์งํฉ์
๋๋ค. ๋๋ฆฌ์ธ. ์ด๋ฅผ ํตํด ES base-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
${infer T}.${infer U} ? [T, U] : never
๋ ["foo", "bar.baz"]
์ด ์๋๋ผ ["foo.bar", "baz"]
["foo", "bar.baz"]
๋ฐํํฉ๋๋ค.
๊ธฐ์ ์ ์ธ ๊ด์ ์์ ์ด๊ฒ์ ์์ ์ ๊ท ํํ์๋ณด๋ค ๊ตฌํํ๊ธฐ์ ํจ์ฌ ๋ ์ ํฉํฉ๋๋ค. JS ์ ๊ท ํํ์์ ๊ท์น์ ์ด์ง ์์ต๋๋ค. ์ญ์ฐธ์กฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ํฉ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ฉฐ ๋ค์ ํ์์ผ๋ก ๋ง์ ๋ณต์ก์ฑ์ ์๋ฐํฉ๋๋ค. ์ด๋ฌํ ๋ฐฉ์์ผ๋ก ์ฌ๊ท๋ฅผ ์ฐจ๋จํ๋ ํ ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด ์ ํ์ ๊ฐ๊ฐ ํ๋์ ์ ๊ท ์ธ์ด๋ฅผ ์์ฑํฉ๋๋ค. ๊ธฐ๋ณธ ์ด๋ก ๊ณผ ๋งค์ฐ ๋ฐ์ ํ๊ฒ ์ผ์นํฉ๋๋ค(๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ํ์ ์งํฉ๋ง ์ง์ํจ).
""
"a" | "b"
`${a}${b}`
starof T
( T
์๋ ๋จ์ผ ๋ฌธ์ ๋ฐ ๊ณต์ฉ์ฒด๋ง ํฌํจ๋ ์ ์์ต๋๋ค.)์ด ๋ฌธ์์ด์ ๋ถ๋ถ ์งํฉ ํ์ธ ํ์ ์ ํ ๋ง๋ค ์ ์์ต๋๋ค ์๋ธ ๊ทธ๋ํ์ ๋ํ ๋ฌธ์ ๊ฐ ์ต์ ์ ์๋๋ฆฌ์ค๋ฅผ, ๊ทธ๋ฌ๋ ์ฝ๊ฐ ํฐ ๊ตฌ์ ์์ธ์ ์ฌ๊ธฐ์ ์์ต๋๋ค :
์ง๊ธ๊น์ง ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ๋ ๋๋ฌด๋ก ๋ชจ๋ธ๋งํ ์ ์๋ ์์ ์ ํ ๋ฌธ์์ด์ ํฉ์งํฉ์ ๋๋ค. ์ด๊ฒ์ ์์ ํ๊ธฐ์ ๋น๊ต์ ๋ถ๋ช ํฉ๋๋ค. (์์ ์ผ์น ์๊ณ ๋ฆฌ์ฆ์ด ๋ณต์กํด์ง๊ธฐ ๋๋ฌธ์ ๋กํ๋ก ๊ฒฐํฉํ๋ ๊ฒ์ ๊ถ์ฅํ์ง ์์ง๋ง ๋จ์ผ ๋ฌธ์ ๊ฒฐํฉ ๋ฐ ์ ์ฌํ ๋จ์ผ ๋ถํ + ๊ฒฐํฉ์ผ๋ก ์ ๊ทํํ๋ ๊ฒ์ ์๋ฒฝํ๊ฒ ๊ด์ฐฎ์ต๋๋ค.)
์ ์ฒด ํตํฉ ์ ํ์ ๋ฐฉํฅ ๊ทธ๋ํ๋ก ๋ชจ๋ธ๋งํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์:
์ด Math.SE ์ฑํ
์ ๋ฐ๋ฅด๋ฉด (์ฝ ์ฌ๊ธฐ ์์ ์์) ์ด ๊ฒฐ๊ณผ ๊ทธ๋ํ์๋ ๊ฒฝ๊ณ๊ฐ ์๋ ์(์ฆ, ๋ค๋ฅธ ๊ฐ์ฅ์๋ฆฌ์ ๋ํ ์ ํํ ์์ ์ ํ*)์ด ์๊ณ starof
์๋ ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค. ์ ํ ํ๋ฑ ์ด ์ด๋ฅผ ๊ฐ๋ ฅํ ์์ฌํฉ๋๋ค. (์์ ๋งํฌ๋ Wikipedia ๊ธฐ์ฌ์๋ "์๊ณ ๋ฆฌ์ฆ"์ ๋ช ๊ฐ์ง ์๊ฐ ์์ผ๋ฉฐ ํน์ ๋์๋ฌธ์๊ฐ ์ ์ฉ๋ ์ ์๋ ์น์
์ ์ฐธ์กฐํฉ๋๋ค.)
์ด๋ฌํ ํค ์ค ์ด๋ ๊ฒ๋ ์ฌ๊ธฐ์ ์ค์ ๋ฐํ์ ๋น์ฉ ๋๋ฌธ์ ๋๋ถ๋ถ์ ๋ค๋ฅธ ๊ฒ๋ค์ ์ํด ์ค์ ๋ก ์๊ฐํ๊ณ , ํฐ ๋ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. ์์ ํค์ ๊ฒฝ์ฐ ๋น ๋ฅด๋ฉด ์ถฉ๋ถํฉ๋๋ค.
๋น๊ต๋ ๋ชจ๋ ํ์ ๊ทธ๋ํ๋ ๋ฃจํธ ๋ ธ๋์ธ ์ ์ด๋ ํ๋์ ๋ ธ๋๋ฅผ ๊ณต์ ํฉ๋๋ค. (์ด๊ฒ์ ๋ฌธ์์ด์ ์์์ ๋ํ๋ ๋๋ค.) ๋ฐ๋ผ์ ์ด๊ฒ์ ๊ทธ ์์ฒด๋ก ๋ฌธ์ ๊ณต๊ฐ์ ๊ทน์ ์ผ๋ก ์ค์ด๊ณ ๋คํญ์ ์๊ฐ ๊ฒ์ฌ๋ฅผ ๋ณด์ฅํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ฌผ๋ก ์ด๋ฌํ ์ ํ ๊ฐ์ ๊ต์ฐจ๋ ์ฌ์ํ์ง ์์ง๋ง ์์ ์ ํ ์ฌํญ์ผ๋ก ์ธํด ์ ์ฌํ ์ํ ์์๊ฐ ์กด์ฌํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ํนํ, ๋ง์ง๋ง ์ ํ์ ๋ถ๋ช ํ ๋คํญ์ ์๊ฐ์ผ๋ก ๋ง๋ญ๋๋ค.
* ์ํ์ ์ผ๋ก ์์ ์ฐ๋ฆฌ ํ๋ก๊ทธ๋๋จธ๋ค์๊ฒ ๋ค์ ์ง๊ด์ ์ด์ง ์๊ฒ ์ ์๋์ง๋ง(์ ํ ์์ด ๊ทธ๋ํ๋ฅผ ๊ทธ๋ฆฌ๊ธฐ ์ํด ํ๋ฉด์ ์ฐ๋ฌ์ผ ํ๋ ์ต์ ๊ตฌ๋ฉ ์), ์ ํ๋ ์(๊ตฌ๋ฉ ์ ์ ํ)์ ์ ํ๋ ์์ ์ ํ๋ฅผ ์๋ฏธํฉ๋๋ค. .
์ด ๊ตฌ์ฒด์ ์ธ ์ ์์ ์ฌ์ฉํ์ฌ ์ด ์ฃผ์์ ์๋ฅผ ๋ฒ์ญํ๋ ๋ฐฉ๋ฒ์
// 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://link.medium.com/0wS7vgaDQV
์ ํ ๊ณต๊ธ์๊ฐ ๊ตฌํ๋๊ณ ์ ๊ท์ ์ ํ ๊ณต๊ธ์๊ฐ ์คํ ์์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๊ตฌํ๋๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ๊ฒ์ด๋ผ๊ณ ์์ํ ์ ์์ต๋๋ค.
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 ์ ์ด๋์ด ์์ฒญ์ ๋ํด์๋ ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ด ์๋๋ผ๊ณ ํ์ ํฉ๋๋ค.
RegexProvider</^foo$/>
๊ฐ "foo"
์ ๋๋ฑํ๊ฒ ์ทจ๊ธ ๋์ง ์๊ณ ๊ทธ๊ฒ์ ๋ช
๋ชฉ ํ์ ์ ํ์ธ ๋ช
๋ชฉ string
ํ์ ์ ํ์ ์์ฑํฉ๋๋ค. ๊ฒ๋ค๊ฐ RegexProvider</^foo$/>
์ RegexProvider</^fo{2}$/>
๋ ๋ณ๊ฐ์ ๋ ๊ฐ์ง ์ ํ์ผ๋ก ์ทจ๊ธ๋๋๋ฐ, ์ ๋ ๊ทธ๋ฐ ๊ฒ์ ์ข์ํ์ง ์์ต๋๋ค. ๋์ ๋ด ์ ์์ ํต์ฌ์ ์๋ ๋ฌธ์์ด๊ณผ ์ง์ ํตํฉ๋๋ฉฐ, ํ์ ์ธ์ด ์ธ์ ์ด๋ก ์ ์ง์ ์ ์ธ ์ํฅ์ ๋ฐ์ ์์ฐ์ค๋ฝ๊ฒ ๋ง๋๋ก ํฉ๋๋ค.Key extends `on${infer K}` ? K : never
๋๋ Key extends `${Prefix}${infer Rest}` ? Rest : never
๋ฅผ ํตํด ๋ฌธ์์ด์ ์ผ๋ถ๋ฅผ ์ถ์ถํ ์ ์์ต๋๋ค. ์ ํ ๊ณต๊ธ์๋ ์ด ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง ์์ผ๋ฉฐ ์ด๋ฌํ ๊ธฐ๋ฅ์ด ์ถ๊ฐ ๋์ด์ผ ํ๋ ๊ฒฝ์ฐ ์ด๋ป๊ฒ /.*/
๋์ string
์์ฒด์ ํตํฉํ ๊ฒ์ ์ ์ํฉ๋๋ค. API ๋ณ๊ฒฝ์ด ํ์ํ์ง ์์ผ๋ฉฐ, ๋๋จธ์ง ์ฝ๋ ๊ธฐ๋ฐ๊ณผ ๋๋ถ๋ถ ๋ถ๋ฆฌ๋๋ ์ด๋ก ์ ์ผ๋ก ๋ณต์กํ ๋ ๋ถ๋ถ์ ์ ์ธํ๊ณ ํ
ํ๋ฆฟ ๋ฆฌํฐ๋ด ์ ํ์ ๋ค๋ฅธ ์ ํ์ ํ ๋นํ ์ ์๋์ง ์ฌ๋ถ๋ฅผ ๊ณ์ฐํ๊ณ ๋ฌธ์์ด์์ ์ฌ๋ผ์ด์ค๋ฅผ ์ถ์ถํ๋ ๊ฒ์ ๋ ๊ฐ๋จํ์ง ์๋๋ผ๋ ๋น์ทํฉ๋๋ค. , ๊ตฌํ.BTW, ๋ด ์ ์์ ์ฌ์ ํ 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}$/>๋ ๋ ๊ฐ์ง ๊ณ ์ ํ ์ ํ์ผ๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค.
ํ์ ๊ณต๊ธ์๋ ์ผ๋ถ 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"
์ ํ์ ์ ํ์ ํ ๋นํ ์ ์์ต๋๊น? (๊ทธ๋ ๋ค๋ฉด ๊ตฌํ์ด ๋ณต์กํด์ง๊ณ ๊ฒ์ฌ๊ธฐ๊ฐ ๋ง์ด ๋๋ ค์ง๋๋ค.)
๋น๋ฉดํ ๋
ผ์์ ๊ด๋ จ์ด ์๋๋ฐ, ์ ํ์ด ๊ณ ์ ๋ ๊ธธ์ด๊ฐ ์๋ ๊ฒฝ์ฐ(์: ์ ํ๋ฒํธ) ์ด๋ป๊ฒ ๋๋์? ์ต๊ทผ์ ์ด๊ฒ์ ์ฌ์ฉํ๊ณ ์ถ์๋ ํ ๊ฐ์ง ์ํฉ์ thread_{number}
ํ์์ ๋ฐฉ ์ด๋ฆ์ ์ ์ฅํ๋ ๊ฒ์
๋๋ค.
์ด๋ฌํ ๊ฐ๊ณผ ์ผ์นํ๋ ์ ๊ท์์ thread_[1-9]\d*
์
๋๋ค. ์ ์๋ ๋ด์ฉ์ผ๋ก๋ ๊ทธ๋ฌํ ํ์์ ์ผ์น์ํค๋ ๊ฒ์ด ์คํ ๊ฐ๋ฅํ์ง ์๊ฑฐ๋ ์ฌ์ง์ด ๊ฐ๋ฅํ์ง๋ ์์ต๋๋ค. ๊ฐ์ ์ซ์ ๋ถ๋ถ์ ์ด ์ํฉ์์ 0๋ณด๋ค ํฐ _any_ ๊ธธ์ด๊ฐ ๋ ์ ์์ต๋๋ค.
@jhpratt ๋๋ ๊ทธ๊ฒ์ ์์ฉํ๊ธฐ ์ํด starof ("0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9")
โ /^\d*$/
ํํ๋ก ์ ์์ ์์ ํ์ต๋๋ค. ์๋ํ๋ฉด ์ฝ๊ฐ๋ง ๋ณ๊ฒฝํ๋ฉด ๋์๊ธฐ ๋๋ฌธ์
๋๋ค. string
๊ฐ /^[\u0000-\uFFFF]*$/
๋ก ์ต์ ํํ๋ ๊ฒ๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ต์ ํํ๋ฏ๋ก ์ผ๋ฐํํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
๊ณ์ฐ ๋ณต์ก์ฑ ๋ฌธ์ ๋ก ์ธํด ์์์ ๋น์ฌ๊ท์ ํฉ์งํฉ์ ํ์ฉํ๋ ๊ฒ๊ณผ ๊ฐ์ด starof
๊ทธ ์ด์์ผ๋ก ํ์ฅํ๊ณ ์ถ์ง ์์ต๋๋ค. ๋ ๊ฐ์ ์์ ์ ๊ท์*์ด ๋์ผํ์ง ํ์ธํ๋ ๊ฒ์ ๋คํญ์ ๊ณต๊ฐ ๋๋ ๋คํญ์ ์๊ฐ ( ๋ ๋ค ์ต์ DFA๋ก ๋ณํํ๊ณ ๋น๊ตํ์ญ์์ค - ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ด์ง๋ง ์ค์ ๋ก๋ ๋งค์ฐ ๋๋ฆผ). ๊ทธ๋ฌ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ ๋ชจ๋ ์ค์ ๋ก๋ a{2}
). ๊ธฐ๋ณธ์ ์ผ๋ก ๋ถ๊ฐ๋ฅํฉ๋๋ค(์ง์ ๋ณต์ก์ฑ) . ์ด๊ฒ์ ๋๋ฑ์ฑ์ ์ํ ๊ฒ์ด๋ฉฐ, ํ ๋น ๊ฐ๋ฅ์ฑ์ ํ์ธํ๋ ๋ฐ ํ์ํ ์ ๊ท ํํ์์ด ๋ค๋ฅธ ์ ๊ท ํํ์๊ณผ ์ผ์นํ๋ ๋ฌธ์์ด์ ํ์ ์งํฉ๊ณผ ์ผ์นํ๋์ง ํ์ธํ๋ ๊ฒ์ ๋ถ๋ช
ํ ํจ์ฌ ๋ ๋ณต์กํ ๊ฒ์
๋๋ค.
* ์ํ์ ์ธ ์๋ฏธ์ ์ ๊ท์: ()
, (ab)
, (a|b)
๋ฐ (a*)
, ์ฌ๊ธฐ์ a
๋ ๋จ์ผ ๋ฌธ์๋ง ํฌํจํฉ๋๋ค (a|b)
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;
๋์ฐํฉ๋๋ค. ์ ์ํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ํ์ง๋ง ๊ทธ๊ฒ์ ํ์คํ ๋์ ์๊ฐ์ ๋๋ค.
์ด ํจ์ ๋ ๋ฐํ์ (๋ณ์, ํจ์)
์ปดํ์ผ๋ฌ๊ฐ์๋ ๊ฒฝ์ฐ ๋ฌผ๋ก ๊ทธ๋ค์, ECMA ์คํฌ๋ฆฝํธ๋ ์ฌ์ฉํ ์ ๋ฐํ์ ์ ( tsc
BTW, ์์ต๋๋ค!). fetch()
์ ๊ฐ์ ์ปดํ์ผ ์๊ฐ ์๋ฏธ์ ๋ฐํ์ ์๋ฏธ์ ๋ชจํธ์ฑ ๋ฌธ์ ๊ฐ ๋ถ๋ช
ํ ์์ง๋ง ์ด๊ฒ์ด ๋ฐ๋ก ๋ฐ๋ณต์ ๊ดํ ๊ฒ์
๋๋ค.
๋ฐํ์ ์ฝ๋๊ฐ ์ปดํ์ผ ์๊ฐ์ ์คํ๋๋๋ก ๋ฌด์์๋ก ํ์ฉํ๋ ๊ฒ์ด "PHP ๋ฐฉ์"์ด ๋ ๊ฒ์ ๋๋ค.
C++ constexpr
functions ์ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ํด๊ฒฐ์ฑ
์ constexpr
๋ constexpr
๋ง ์ฌ์ฉํ ์ ์์ง๋ง ๋ชจ๋ ๊ฒ์ด constexpr
์ฌ์ฉํ ์ ์๋ค๊ณ ๋งํ๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฐ ๋ค์ ์๋นํ ๊ฐ๋ ฅํ ์ ์๋ ์ปดํ์ผ ํ์ ํ์ผ ์์คํ
์ ๋ํด constexpr
-๋๋ฑํ ๋ฒ์ ์ ํ์ผ ์์คํ
์ ๊ฐ์ง ์ ์์ต๋๋ค.
๊ตฌ๋ฌธ๋ ๋๋ต ๊ด์ฐฎ์ ๋ณด์ ๋๋ค. LHS๋ ์ ํ์ด๊ณ ๋ฌผ๋ก RHS๋ ์ผ์ข ์ ์ ํ์ ๋๋ค. ๋ด ๋ฌธ์ ๋ "๊ธฐ๋ณธ" ์ ํ์ ๋์ด ์ ํ์ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ๊ดํ ๊ฒ์ด์ง๋ง ๊ทธ๊ฒ๋ ๋ชจ๋ ํด๊ฒฐํ ์ ์์ต๋๋ค.
์ ์ํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ํ์ง๋ง ๊ทธ๊ฒ์ ํ์คํ ๋์ ์๊ฐ์ ๋๋ค.
๊ทธ๊ฒ์ ๊ฒฐ๊ตญ ๋์ ์๊ฐ์ด ๋ ์ ์์ง๋ง ์ง๊ธ์ ํ์ดํ์คํฌ๋ฆฝํธ์ ๋ชฉํ์์ ๋๋ฌด ๋ฉ๋ฆฌ ๋ฒ์ด๋์ผ ํ ๊ฐ๋ฅ์ฑ์ด ์๋ ๋งค์ฐ ๋ ๊ตฌ์ฒดํ๋ ์์ด๋์ด๋ฅผ ๋ณด๊ณ ์์ต๋๋ค. ๊ทธ๊ฒ๊ณผ ์ ์ฌํ ์ข์ ์์ด๋์ด๊ฐ ์์ ์๋ ์๋ค๋ ์๋ฏธ๋ ์๋๋๋ค!
์ด ๊ธฐ๋ฅ์ ๋ํ ๋ ผ์๋ ์ง๊ธ์ ์ค๋จ๋ ๊ฒ ๊ฐ์ต๋๋ค( 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
๊ทธ๋ฌ๋ ํจ์ ๋งค๊ฐ๋ณ์์์ Regex ์ ํ์ ์ฌ์ฉํ ๋ ๊บพ์ ๊ดํธ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ ์ผ์นํ๋ ๋ฌธ์์ด์ ์ถ๋ก ํ๋ ค๋ ๊ฒ์ ์๋ฏธํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด
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"]
๋ค์ ์ฝ๋๊ฐ ์๋ํ๋๋ก ์ ํ ์์ "๋ฌธ์์ด ๊ฒฝ๋ก" getter๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
const deep = get(objNested, "nested.very.deep")
๊ทธ๋ฌ๋ ๊ฐ๋ฅํ get
์ "๊น์ด"์ ๊ณ ์ ๋ ์ต๋ ์์ ๋ํด ๋ง์ ๊ณผ๋ถํ๋ฅผ ํผํ๋ ค๋ฉด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ ๊ฒ์
๋๋ค.
์๋ฅผ ๋ค์ด https://github.com/Microsoft/TypeScript/issues/12754 ์ ๊ฐ์ ์์
์ ์ํํ ์ ์๋ค๋ฉด { [ StripAsyncSuffix<P> for P in K ] : T[P] }
์ ๊ฐ์ ๊ตฌ๋ฌธ, ๋๊ตฐ๊ฐ ์ด๋ฏธ ์ด์ ์ ์ฌํ ๊ฒ์ ์ ์ ํจ)
์๋ง ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก๋ ์์ ๊ฒ์ ๋๋ค. ํ์ง๋ง ๋๋ถ๋ถ์ ์ด ๋ ๊ฐ์ง ์ ํ์ ์ ํฉํ ๊ฒ ๊ฐ์ต๋๋ค(1. ์ ๊ณต๋ ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ ๊ธฐ๋ฐ์ผ๋ก ์ ์ ํ ์ ํ ํ์ , 2. ์ ๋ ฅ ์ ํ์ ์์ฑ ์ด๋ฆ์ ์๋ก ์ ์๋ ์ ํ์ ์ ์์ฑ ์ด๋ฆ์ผ๋ก ๋ณํ)
์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ํ ์ ์๋ ์ผ์ ๋๋ค.
์ ๋ ํ์ฌ URL์ ์ ํจ์ฑ์ ๊ฒ์ฌํ ์ ์๋๋ก ๋ง์ถค ๋ฆฐํธ ๊ท์น์ ๋ง๋ค๊ณ ์์ต๋๋ค. ํ์ง๋ง ์ ํ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ ์ํ ์ ์๋ค๋ฉด ํจ์ฌ ๋ ์ฌ์ธ ๊ฒ์ ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ์ด๊ฒ์ ์ฝ๋ ๊ธฐ๋ฐ ์ ์ฒด์์ props์ ์ ํจ์ฑ์ ์ฃผ์ฅํ ์ ์๋ ํจ์ฌ ๋ ๋ง์ ๊ถํ์ ์ ๊ณตํฉ๋๋ค.
์ ํ ๊ณต๊ธ์, ํ ํ๋ฆฟ ๋ฌธ์์ด ๋ฆฌํฐ๋ด ๋๋ ๊ธฐํ ์ ์์ ๋ํ ์ด๋์ด ์์ต๋๊น? ์ด๊ฒ์ ํ๋ฅญํ ๋๊ตฌ๊ฐ ๋ ๊ฒ์ ๋๋ค.
์ด์ ๋ํ ๋์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ํ์ฌ์ ๊ฐ์ ๋ง์ปค ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค ์ด .
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
์์ ์ ์์ ๊ฒํ ํ์ผ๋ฉฐ ๋ช ๊ฐ์ง ์ง๋ฌธ๊ณผ ์๊ฒฌ์ด ์์ต๋๋ค.
์ฐ๋ฆฌ๋ ์ ํ ์์คํ ์ ์์ ํ ์ง์ฐ๊ธฐ ์ํด ์ต์ ์ ๋คํ๊ณ ์์ผ๋ฏ๋ก ๋ฐฉ์ถ๋ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํด ์ ํ ๋ณ์นญ์ด ํ์ํ ์ ์์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ฉ๋๋ค. ์ด ์ค๋ ๋์์ ๋ช ํํ์ง ์์ ๋ฐฉ์์ผ๋ก ๋ฐ์ํ ๋ช ๊ฐ์ง ์๋ฅผ ๊ฐ์กฐํ๊ฒ ์ต๋๋ค.
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");
์ค์ ๋ก ์ผ๋ฐ์ ์ธ ์ ํ๊ณผ ์ ๊ท์์ผ๋ก ๊ฒ์ฆ๋ ์ ํ์ ์ค์ ๋ก ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ํฉ์งํฉ๊ณผ ๊ต์ฐจ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๊ท์น์ด ํ์ํฉ๋๋ค.
type Regex_1 = / ... /;
type Regex_2 = / ... /;
type NonRegex = { ... };
type test_4 = Regex_1 & NonRegex;// compile time error
TypeScript๋ ๊ต์ฐจ์ ์ธ์คํด์คํ์์ ์ค๋ฅ๋ฅผ ๋ฐ์์ํฌ ์ ์์ผ๋ฏ๋ก ์ด๊ฒ์ ์ต์ข ๋์์ธ์ ์ผ๋ถ๊ฐ ์๋๋๋ค.
์ ๋ฐ์ ์ผ๋ก ๊ฐ์ฅ ๋๋๋ฌ์ง ์์ฌ์ ์ ๋์ผํ RegExp๋ฅผ ๋ ๋ฒ (๊ฐ ๊ณต๊ฐ์์ ํ ๋ฒ, ์ ํ ๊ณต๊ฐ์์ ํ
์ ํ ๋ฐฉ์ถ์ ๋ํ ์์ ์ฐ๋ ค๋ฅผ ๊ฐ์ํ ๋ ๊ฐ์ฅ ํ์ค์ ์ธ ์๋ฃจ์ ์ ๊ฐ ๊ณต๊ฐ์ ํํ์์ ์์ฑํ๋ ๊ฒ์ ๋๋ค.
// 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
๋ฌผ๋ก ์ฌ์ ํ RegExp๋ฅผ ํ์ ๊ณต๊ฐ์ ์์ฑํ ์ ์์ง๋ง ๋ฐํ์ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ๋ฌธ์๊ฐ ์๋ ์ฌ์ฉ์๋ ๋ค์ ํ ์คํธ ๋๋ ์ด์ค์ ์ด ํ์ํฉ๋๋ค.
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);
}
}
์๋ก์ด ์ ํ์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ ๋ช ๊ฐ์ง ์๋ฅผ ์ด์์ ์ผ๋ก ๋ณด๊ณ ์ถ์ต๋๋ค.
์ด ์ค๋ ๋๋ ๋ค์ํ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์๋ฏธํฉ๋๋ค. ๊ตฌ์ฒด์ ์ธ ์๋ ๋ ๋๋ฌผ์๋ค. ๋ฌธ์ ๋ ์ด๋ฌํ ์ ์ค ๋ง์ ๋ถ๋ถ์ด ์์ ํ์ง ์๋ค๋ ๊ฒ์ ๋๋ค. ์ ํจํ ์ ๋ ฅ์ ๊ฑฐ๋ถํ๋ RegExp๋ฅผ ์ฌ์ฉํฉ๋๋ค.
rgb(255, 0, 0)
๊ตฌ๋ฌธ์ ์๋ชป ๊ฑฐ๋ถํฉ๋๋ค."3e5"
์๋ชป ๊ฑฐ๋ถํฉ๋๋ค.Date
์๋ ์ด๋ฅผ ์ํ ์์ฑ์๊ฐ ์์ต๋๋ค. ์
๋ ฅ์ด ๋ฐํ์ ์ธ๋ถ์์ ์ค๋ ๊ฒฝ์ฐ ๋ช
๋ชฉ ์ ํ์ ์ํฉ๋๋ค.fetch
์ง์ ํฉ๋๋ค host
๋ก๋์ง ์๋์ http(s?):
TODO: RegExp ์ ํ์ ์ด์ ์ ์ป์ ์ ์๋ ์ค์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์์ ์ฌ์ฉํ ์ค์ ํํ์์ ์๋ณํ์ฌ ์ ํฌ๋ฅผ ๋์์ฃผ์ธ์.
ํ ๊ฐ์ง ์ฐ๋ ค ์ฌํญ์ "์ ๋ฐ๋์ผ"์
๋๋ค. ๋๊ตฐ๊ฐ๊ฐ ํ์คํ Typed์ ์ ์ฉํ๊ฒ ํ์๋๊ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ชจ๋ ํจ์์ RegExp ์ ํ์ ์ถ๊ฐํ์ฌ ๋ชจ๋ ๋น๋ฌธ์์ ํธ์ถ์ด ์ค๋จ๋๋ฉด ์ด๋ป๊ฒ ๋ฉ๋๊น? ์ค์๊ฐ์์ผ๋ก ์ ์ ํ์ผ ์์ฑ์๋ ์ ํจ์ฑ ๊ฒ์ฌ RegExp์ "์ฌ๋ฐ๋ฅธ ์ฒ ์"๊ฐ ๋ฌด์์ธ์ง ์๋น์์ ์ ํํ ๋์ํด์ผ ํฉ๋๋ค.
์ด๊ฒ์ ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ URL๋ก ์๊ฒฉ์ด ์๋ ๊ฒ, ํธ์คํธ ์ด๋ฆ์ผ๋ก ์๊ฒฉ์ด ์๋ ๊ฒ, ์ด๋ฉ์ผ๋ก ์๊ฒฉ์ด ์๋ ๊ฒ ๋ฑ์ ๋ํ ์์ฒด ๋ฒ์ ์ด ์๊ณ ๋ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐ๊ฒฐํ๋ ์ฌ๋์ด ์๋ ๋ฐ๋ฒจํ ์ํฉ์ผ๋ก ๋น ๋ฅด๊ฒ ์ฐ๋ฆฌ๋ฅผ ์๋ดํ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ปดํ์ผ๋ฌ๋ฅผ ๋ง์กฑ์ํค๊ธฐ ์ํด ํ์ ์ฃผ์ฅ์ ์ฝ์
ํ๊ฑฐ๋ ์ ๊ท ํํ์์ ๋ณต์ฌํด์ผ ํฉ๋๋ค.
์ด์ ์ธ์ฒด ๊ณตํ ์น์
์ fn
์ ๊ฐ์ด ํจ์์ ์ธ์๊ฐ ์ด์ ์ ๊ท์์ ์ํด ๊ฒ์ฆ๋์๋์ง ํ์ธํ๋ ค๋ ๊ฒ์ฌ์ ๋ํ ๋
ผ์๊ฐ ์์์ต๋๋ค. ํ
์คํธ๊ฐ ํ์ํ RegEx๊ฐ ์ ์๋ ค์ง ๊ฒฝ์ฐ ์ด๋ ๊ฐ๋จํ๊ณ ๊ฐ์น๊ฐ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ํฐ "๋ง์ฝ"์
๋๋ค. ์ ๊ธฐ์ต์ผ๋ก๋ ์ ํจ์ฑ ๊ฒ์ฌ ์ ๊ท์์ ์ ๊ณตํ๋ ๋จ์ผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๊ธฐ์ต๋์ง ์์ต๋๋ค. ์ ํจ์ฑ ๊ฒ์ฌ ๊ธฐ๋ฅ์ ์ ๊ณตํ ์ ์์ง๋ง ์ด๋ ์ ๊ณตํ
์ด ํ๊ฐ์ ๋ํ ๋ฐ๋ ์ฆ๊ฑฐ๋ ํ์ํฉ๋๋ค.
์ผ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์์ฑ ์ด๋ฆ์ ๋ฐ๋ผ ๊ฐ์ฒด๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์๋ฅผ ๋ค์ด 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 ๊ธฐ๋ฅ์ ์๋นํ ๋ํดํ๊ฑฐ๋ ๊ทธ๋ฃน ์ผ์น์ ๊ด๋ จ๋์ด ์ฌ๊ธฐ์์ ๋๋ถ๋ถ์ ์ฌ์ฉ ์ฌ๋ก์ ์ผ์นํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
RegExes๋ ๋ฌดํํ ์์ ์์ ์ ์ํํ ์ ์์ผ๋ฉฐ ํฐ ๋ฌธ์์ด์ ๋ํ ์ผ์น๋ ์์๋ก ๋ง์ ์์ ์์ ์ ์ํํ ์ ์์ต๋๋ค. ์ฌ์ฉ์๋ ์ด๋ฏธ ๋ค๋ฅธ ์๋จ์ ํตํด ์ค์ค๋ก DOS๋ฅผ ์ํํ ์ ์์ผ๋ฉฐ ์ ์์ ์ผ๋ก ๋นํจ์จ์ ์ธ RegExp๋ฅผ ์์ฑํ ๊ฐ๋ฅ์ฑ์ ๊ฑฐ์ ์์ต๋๋ค.
/\d*/
->
/.*/
?), ์กฐํฉ, ๊ต์ฐจ๋ก ๋ฐ ๊ฑฐ์ฃผ ๋ถ๊ฐ๋ฅ์ด๋ก ์ /\d+/
๋ /.+/
์ ์ ์ ์๋ ํ์ ์ ํ์
๋๋ค. ํ RegExp๊ฐ ๋ค๋ฅธ RegExp์ ์์ํ ํ์ ์งํฉ๊ณผ ์ผ์นํ๋์ง(ํน์ ์ ์ฝ ์กฐ๊ฑด์์) ๊ฒฐ์ ํ๋ ์๊ณ ๋ฆฌ์ฆ์ด ์กด์ฌํ์ง๋ง ๋ถ๋ช
ํ ํํ์์ ๊ตฌ๋ฌธ ๋ถ์ํด์ผ ํฉ๋๋ค. ์ค์ ๋ก ์ฐ๋ฆฌ๋ RegExpes๊ฐ ์ผ์นํ๋ ํญ๋ชฉ์ ๋ฐ๋ผ ์์์ ํ์ ์ ํ ๊ด๊ณ๋ฅผ ํ์ฑํ์ง ์๋ ๊ฒ์ ๋ํด 100% ๊ด์ฐฎ์ต๋๋ค. ์ด๊ฒ์ ์๋ง๋ ๋ ๋ฐ๋์งํฉ๋๋ค.
ํ ๋น ๊ฐ๋ฅ์ฑ ๊ด๊ณ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ ์๋์ด ์๋ ํ Union ๋ฐ Intersection ์์ ์ "์ฆ์" ์๋ํฉ๋๋ค.
TypeScript์์ ๋ ๊ฐ์ ๊ธฐ๋ณธ ์ ํ์ด ๊ต์ฐจ์ ์์ "์ถฉ๋"ํ๋ฉด never
์ค์ด๋ญ๋๋ค. ๋ ๊ฐ์ RegExp๊ฐ ๊ต์ฐจํ ๋ ๋ ํํ์์ ๊ต์ฐจ์ ์ผ์นํ๋ ์ RegExp๋ฅผ ์์ฑํ๋ ๋์ /a/ & /b/
๋ก ์ ์งํฉ๋๋ค. never
๋ก์ ๊ฐ์๋ ์์ ๊ฒ์
๋๋ค. ์ฐ๋ฆฌ๋ ์ด๋ค ๋ฌธ์์ด๋ ์์ชฝ์ ๋ง์กฑ์ํฌ ์ ์๋ค๋ ๊ฒ์ ์ฆ๋ช
ํ๋ ์๊ณ ๋ฆฌ์ฆ์ด ํ์ํฉ๋๋ค(์ด๊ฒ์ ์์์ ์ค๋ช
ํ re: subtyping๊ณผ ์ ์ฌํ ๋ฌธ์ ์
๋๋ค).
์์ฝํ๋ฉด ๋ค์ ๋จ๊ณ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ฌ์ฉ ์ฌ๋ก: ํ์ดํผ์คํฌ๋ฆฝํธ(https://github.com/hyperhype/hyperscript)์ ๊ฐ์ ๊ธฐ๋ฅ
ํ์ดํผ์คํฌ๋ฆฝํธ ํจ์๋ ์ผ๋ฐ์ ์ผ๋ก h('div#some-id')
์ ๊ฐ์ด ํธ์ถ๋ฉ๋๋ค.
regex-ish ํจํด ๋งค์ฒ๋ 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>;
}
์ฌ์ฉ ์ฌ๋ก: ํ์ดํผ์คํฌ๋ฆฝํธ(ํ์ดํผํ์ดํ/ํ์ดํผ์คํฌ๋ฆฝํธ) ์ ์ฌ ํจ์
ํด๋น ์ ๊ท์์ ์ด๋ป๊ฒ ์๊ฒผ์ต๋๊น? ๋๋ ์ด๋ค ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ ๊ณตํฉ๋๊น? ์ ๊ท์ ๊ธฐ๋ฐ ํจ์ ์ค๋ฒ๋ก๋ฉ์ ์ํ ๊ฒ์ ๋๊น?
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 ์ ํ์ ์ด์ ์ ์ป์ ์ ์๋ ์ค์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์์ ์ฌ์ฉํ ์ค์ ํํ์์ ์๋ณํ์ฌ ์ ํฌ๋ฅผ ๋์์ฃผ์ธ์.
๋ด ์ฌ์ฉ ์ฌ๋ก๋ TickerSymbol
๋ฅผ ๋ํ๋ด๋ ๋ฌธ์์ด์ด ์๋ CCXT ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ด ์ฃผ์ ์์ ์ค๋ช
ํ ๊ฒ์
๋๋ค. ์ ๊ท์ ํจํด์ ํ์ธํ๋์ง ์ฌ๋ถ๋ ๋ณ๋ก ์ ๊ฒฝ ์ฐ์ง ์์ง๋ง string
์ ํ์ ์ ํ์ผ๋ก ์ฒ๋ฆฌ๋๊ธฐ๋ฅผ ์ํ๋ฏ๋ก ๋ ์๊ฒฉํ ํ ๋น, ๋งค๊ฐ๋ณ์ ์ ํ ๊ฒ์ฌ ๋ฑ์ ์ป์ต๋๋ค. ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ํ ๋ ๋งค์ฐ ์ ์ฉํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ฐํ์์๋ ๊ทธ๋ฅ ์ผ๋ฐ ๋ฌธ์์ด์ธ TickerSymbols, Currencies, Assets ๋ฑ์ ์ปดํ์ผ ํ์์ ์ฝ๊ฒ ์ถ์ ํ ์ ์์ต๋๋ค.
@omidkrad ์ด๊ฒ์ ์ ๊ท์ ๊ฒ์ฆ ์ ํ์ด ์๋ ๋ช ๋ชฉ ์ ํ ์ด ํ์ํ ๊ฒ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค.
@m93a ์ ๊ฒฝ์ฐ์๋ ๋ช ๋ชฉ ์ ํ์ผ๋ก ๋ฌธ์ ๊ฐ ์์ง๋ง ๋์ผํ ์ฌ์ฉ ์ฌ๋ก์ ๊ฒฝ์ฐ ๋ ์๊ฒฉํ ์ ํ ๊ฒ์ฌ ๋ฐ ๋ฌธ์์ด ์ ํ ์์ฒด ๋ฌธ์ํ๋ฅผ ์ํด ์ ๊ท์ ๊ฒ์ฆ ์ ํ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
CSS ์ ํ๊ธฐ์ ์ ํจ์ฑ๋ ๊ฒ์ฌํ ์ ์์ต๋๋ค.
CSS ์ ํ๊ธฐ ๋ ์ ๊ท์์ผ๋ก ์ ํจ์ฑ์ ๊ฒ์ฌํ ์ ์์ต๋๋ค.
๊ธ์์, ์ ๊ท ํํ์์ด ๊ทธ๊ฒ๋ค์ ํ๋๋ก ๋ฌถ์ ์ ์๊ฒ ํด์ค๋ค๋ฉด ์ฐ๋ฆฌ๋ CSS ์ ๊ท ํํ์์ ๋ณต์ฌํ ์ ์์ ๊ฒ์ ๋๋ค..., ๊ทธ๋ ์ฃ ?
(์ด์) CSS ์ ํ ๊ฐ์ฒด ๋ชจ๋ธ
https://drafts.css-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};
BTW, ์ด ์ํํ ํตํฉ๊ณผ ๋ณต์ก์ฑ ํํผ๊ฐ ๋ด๊ฐ ์ฌ์ ํ ๋ฆฌํฐ๋ด ์ ๊ท ํํ์๋ณด๋ค ๋ด ์ ์์ ์ ํธํ๋ ์ด์ ์ ๋๋ค.
ํ์ง๋ง ์์ํ ์ ๊ท ํํ์ ์ ํ์ผ๋ก ์ด ์์ ์ ์ํํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ ์ง์ ํ๊ณ ์ถ๋ค.
TODO: RegExp ์ ํ์ ์ด์ ์ ์ป์ ์ ์๋ ์ค์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์์ ์ฌ์ฉํ ์ค์ ํํ์์ ์๋ณํ์ฌ ์ ํฌ๋ฅผ ๋์์ฃผ์ธ์.
Bent ๋ ์์๋๋ ์๋ต ์ ํ์ ์ค๋ช ํ๋ ๋ฌธ์์ด๋ก ์ ๊ณต๋ ๊ฒ์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ฐํ ์ ํ์ ๊ฐ์ต๋๋ค.
bent('json')('https://google.com') // => Promise<JSON>
bent('buffer')('https://google.com') // => Promise<Buffer | ArrayBuffer>
bent('string')('https://google.com') // => Promise<String>
๋ํ method ๋ฐ 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 liErQgwCgkg2ugMWER0EY0QA7tFyFShogZspDAotjyABbAYBgVBmAD0Eqk0XYYApADoSOx + + + Q0 GCBVsgA
์, ์ฃ์กํฉ๋๋ค. ๋ด ๋ฌธ์ ๋ ๊ธฐ๋ณธ URL์ ๊ฐ์งํ๊ธฐ ์ํด ๋ฌธ์์ด ์์ ๋ถ๋ถ์ ์ผ์นํ๋ http(s):
๋ผ์ธ์ ๋ ๊ฐ๊น์ต๋๋ค.
Bent์ ์๋ช ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
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:
๊ฐ ์๋์ง ํ์ธํ๋ฏ๋ก ๊ตฌ๋ถ๋ฌ์ง ์๋ ๋ฐฉ์๊ณผ ์ผ์นํฉ๋๋ค.
์ ๊ท์ ์ ํ์ด ์๋ ๊ฒฝ์ฐ BaseUrl์ type BaseUrl = /^https?:/
๋ก ์ ์ํ ์ ์์ผ๋ฉฐ, ์ด๋ ๊ฒ ํ๋ฉด HTTP ๋ฉ์๋ ๋๋ ์๋ต ์ธ์ฝ๋ฉ์ด ์๋ ๋ฌธ์์ด์ ์ด์์ ์ผ๋ก ํ์ธํ๊ณ string
๋ก ํก์ํ์ง ์์ต๋๋ค. ์ ํ.
์ ํํ๋ ์ ๋ ๋๊ฐ์ต๋๋ค.
--
ํ๋ก์ฝฅ ์๋ฉ
2019๋
10์ 20์ผ 03:23:30, Michael Mitchell([email protected])
์ผ๋ค:
์ค, ๋๋ ๋ด ๋ฌธ์ ๊ฐ
์ผ์นํ๋ http(s): ๋ฌธ์์ด์ ์์ ๋ถ๋ถ์์ ๊ธฐ๋ณธ URL์ ๊ฐ์งํฉ๋๋ค.Bent์ ์๋ช ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ ํ HttpMethods = '๊ฐ์ ธ์ค๊ธฐ' | 'ํจ์น' | ...์ ํ StatusCode = ์ซ์;์ ํ BaseUrl = ๋ฌธ์์ด; // ์ฌ๊ธฐ์์ ๋ฌธ์์ด์ด http(s):type Headers = { [x: string]: any;์ ์ผ์นํ๋์ง ์ด์์ ์ผ๋ก ํ์ธํด์ผ ํฉ๋๋ค. };
์ ํ ์ต์ = HttpMethods | ์ํ ์ฝ๋ | ๊ธฐ๋ณธ URL | ํค๋;
ํจ์ ๋ฒคํธ(...args: ์ต์ []): RequestFunctionํจ์ ๋ฒคํธ(...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=ABJ3U4JNK3V5MV4DJH73ZU3QPOXJFA5CNFSM4BZLAVSKYY1ABBYT0ZY01000003PNVWWK3TUL52HS4DFVREXG43VMVBW63
๋๋ ๊ตฌ๋ ์ทจ์
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');
์ ๊ท ํํ์์ผ๋ก 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
์ ํ ๋นํ ์ ์์ต๋๋ค.
@RyanCavanaugh ์ฐ๋ฆฌ๋ Mithril์ ๋ค์์ ์ฌ๋ฐ๋ฅด๊ฒ ์ ๋ ฅํ๊ธฐ๋ฅผ ์ํฉ๋๋ค.
// <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)
๊ทธ๋ฌ๋ (๋๋ฌด ๋ง์) ์ฌ๋๋ค์ด ์ด๋ ฅ์ ๊ธฐ์ธ์ด๊ณ ๋ชจ๋ ์ ํ ์ฐ์ฐ์๋ฅผ ๋ฏธ์น ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ก ํธํ๋๋ ๊ฒ์ ์ฐจ๋จํ๋ ๊ฒ์ ๋ณด์ง ๋ชปํฉ๋๋ค. ๋๋ ๋์๊ด ์๊ฐ๋ค์ด ์ถฉ๋ถํ ๋์ ํ ๊ฒฝํฅ์ด ์๋ค๊ณ ์๊ฐํ๋ ๊ฒ์ ์ข์ํฉ๋๋ค... ๋ง์ฃ ?
๋ฌธ์์ด ํจํด ์ ํ/์ ๊ท์ ์ ํจ์ฑ์ด ๊ฒ์ฆ๋ ๋ฌธ์์ด ์ ํ์ ์ํ๋ ๊ฒฝ์ฐ๋ ํํ์ง ์์ง๋ง ํ์คํ ๋ด ์ฝ๋ ๊ธฐ๋ฐ์ ์ ํ ์์ ์ฑ์ ๋์ด๋ ๋ฐ ๋์์ด ๋์์ ๊ฒ์ ๋๋ค.
๋จธ๋ฆฌ ๊ผญ๋๊ธฐ์์ ์ต๊ทผ ํ ๊ฐ์ง ์๋ฅผ ์๊ฐํ ์ ์์ต๋๋ค. (๋ ๋ง๊ฒ ์ง๋ง ๋๋ ๊ฑด๋ง์ฆ์ธ)
์คํธ๋ผ์ดํ์ 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
๋ง "์ ํ"ํฉ๋๋ค. ๋ ๊ฐ์ง ๊ฐ๋ง ์์ต๋๋ค.
๊ฐ๋ฐ์๋ true
๋ฐ false
๋ฆฌํฐ๋ด์ ์ฌ์ฉํ๋ ๊ฒ์ ๋ง์กฑํฉ๋๋ค. ์๋ํ๋ฉด ๋ ์ด์ ์๊ตฌํ ๊ฒ์ด ์๊ธฐ ๋๋ฌธ์
๋๋ค.
number
์ ํ์ ์ ํํ์ง๋ง ๊ฐ์ด ๋๋ฌด ๋ง๊ธฐ ๋๋ฌธ์ ๋ฌดํํ๋ค๊ณ ์๊ฐํ ์๋ ์์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ง์ ํ ์ ์๋ ๋ฆฌํฐ๋ด์๋ ๊ตฌ๋ฉ์ด ์์ต๋๋ค.
์ด๊ฒ์ด ๋ฒ์ ๋ฒํธ ์ ํ ๋ฐ NaN, Infinity, -Infinity
๋ฌธ์ ๊ฐ ์ธ๊ธฐ๊ฐ ์๊ณ ๊ณ์ ๋ํ๋๋ ์ด์ ์
๋๋ค. ๋ฌดํ ์งํฉ์์ ์์ ์ ํ ๊ฐ ์งํฉ์ ์ง์ ํ ์ ์๋ค๋ ๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ต๋๋ค.
๋ฒ์๋ฅผ ์ง์ ํ๋ ๊ฒ์ ๋ฌดํ ์งํฉ์ ํฐ ์ ํ/๋ฌดํ ๋ถ๋ถ ์งํฉ์ ์ง์ ํด์ผ ํ ๋ ๋๊ตฐ๊ฐ์๊ฒ ์ค๋ ๊ฐ์ฅ ์ผ๋ฐ์ ์ด๊ณ ์์ฐ์ค๋ฌ์ด ์์ด๋์ด ์ค ํ๋์ ๋๋ค.
bigint
์ ํ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฌดํํ๋ฉฐ ๋ฉ๋ชจ๋ฆฌ์ ์ํด์๋ง ์ ํ๋ฉ๋๋ค.
๋ํ ๋ฒ์ ๋ฒํธ ์ ํ ๋ฌธ์ ์ ์ธ๊ธฐ์ ๊ธฐ์ฌํฉ๋๋ค.
string
์ ํ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฌดํํ๋ฉฐ ๋ฉ๋ชจ๋ฆฌ์ ์ํด์๋ง ์ ํ๋ฉ๋๋ค.
์ด๊ฒ์ด ๋ฐ๋ก ์ด ๋ฌธ์์ด ํจํด ์ ํ/์ ๊ท์ ๊ฒ์ฆ ๋ฌธ์์ด ์ ํ ๋ฌธ์ ๊ฐ ์ธ๊ธฐ ์๋ ์ด์ ์ ๋๋ค.
์ ๊ท์์ ์ง์ ํ๋ ๊ฒ์ ๋ฌดํ ์งํฉ์ ํฐ ์ ํ/๋ฌดํ ํ์ ์งํฉ์ ์ง์ ํด์ผ ํ ๋ ๋๊ตฐ๊ฐ์๊ฒ ์ค๋ ๊ฐ์ฅ ์ผ๋ฐ์ ์ด๊ณ ์์ฐ์ค๋ฌ์ด ์์ด๋์ด ์ค ํ๋์ ๋๋ค.
symbol
ํ์
... ์ญ์ ๋ฌดํ๋์
๋๋ค. ๋ํ ๊ฑฐ์ ๋ฌด์ ํ์
๋๋ค.
๊ทธ๋ฌ๋ symbol
์ ํ์ ์์๋ ๊ฑฐ์ ๋ชจ๋ ๋ฉด์์ ์๋ก ๊ฑฐ์ ๊ด๋ จ์ด ์์ต๋๋ค. ๋ฐ๋ผ์ ์๋ฌด๋ " symbol
์ ํฐ ์ ํ/๋ฌดํ ๋ถ๋ถ ์งํฉ์ ์ง์ ํ ์ ์์ต๋๊น?"๋ผ๊ณ ๋ฌป๋ ๋ฌธ์ ๋ฅผ ์ ๊ธฐํ์ง ์์์ต๋๋ค.
๋๋ถ๋ถ์ ์ฌ๋๋ค์๊ฒ ๊ทธ ์ง๋ฌธ์ ์ดํด๊ฐ ๋์ง ์์ต๋๋ค. ์๋ฏธ์๋ ๋ฐฉ๋ฒ์ ์์ต๋๋ค(๋ง๋์?)
๊ทธ๋ฌ๋ ๊ธฐ๋ณธ ์์์ ํ์ ์งํฉ์ ์ ์ธํ ์ ์๋ ๊ฒ๋ง์ผ๋ก๋ ๊ทธ๋ค์ง ์ ์ฉํ์ง ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ํ์ํฉ๋๋ค,
๊ณ ๋ง๊ฒ๋ TS๋ ์ด๋ฅผ ํ์ฉํ ๋งํผ ์ ์ ์ ์ด ์๋๋๋ค.
false
๋ฅผ (arg : false) => void
๋ก ์ ๋ฌํ ์ ์๋ค๊ณ ์์ํด๋ณด์ธ์!
์ขํ๋ ๋ฐฉ๋ฒ ๋ด์ฅ
ํ์ฌ ์ด๋ฌํ ๋ฆฌํฐ๋ด์ ๊ฒฝ์ฐ ๊ธฐ๋ณธ ์ ๊ณต ์ถ์ ๋ฐฉ์์ผ๋ก ==
& ===
๊ฐ ์์ต๋๋ค.
๊ฐ ๋ฆฌํฐ๋ด์ ๋ํด ์๋ก์ด ์ ํ ๊ฐ๋๋ฅผ ์์ฑํด์ผ ํ๋ค๊ณ ์์ํด๋ณด์ธ์!
๋ช ๋ชฉ/๊ตฌ์กฐ ํ๊ทธ/๊ฐ-๊ฐ์ฒด ์ ํ์ ๋ฌธ์ ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ ๋ ๊ฐ์ง ๊ธฐ์ค์ ์ถฉ์กฑํ์ง ๋ชปํ๋ค๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ค์ ์์ ์ ํ์ ๊ฐ์ฒด ์ ํ์ด ์๋์ง๋ง ์ด์จ๋ ๊ฐ์ฒด ์ ํ์ฒ๋ผ ์ฒ๋ฆฌํด์ผ ํ๋ ํฌ๋ฐํ ์ ํ์ผ๋ก ๋ฐ๊ฟ๋๋ค.
์, ์ฌ๊ธฐ์ ๋ฌธ์์ด ํจํด ๋ ๋ช ๋ชฉ ํ๊ทธ ์ ํ ๋ฐ ๊ตฌ์กฐ ํ๊ทธ ์ ํ์ ๋ํ ์์ธํ ์ค๋ช ์ด ์์ต๋๋ค.
์ด๋ฌํ ์ธ์๋ https://github.com/microsoft/TypeScript/issues/15480 ์๋ ์ ์ฉ๋ฉ๋๋ค.
๋ช
๋ชฉํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐ ํธํ์ฑ ์ด ์ต์
์
๋๋ค.
๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ unique symbol
๋ฅผ ์ฌ์ฉํ๊ณ ์ํธ ์ด์ฉํ๋๋ก ํ๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
๊ทธ๊ฒ์ ๋จ์ํ ํ ์ ์์ต๋๋ค.
์์ฉ๊ตฌ ์ ํ ๊ฐ๋ ๋๋ 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)
๋ฅผ typeguard๋ก ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. trust-me-operator( as
)๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ฃผ์ฅ ๋ณดํธ๋ฅผ ์ํ ์์ฉ๊ตฌ๋ ์ฌ์ ํ ํ์ํฉ๋๋ค.
์ ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐ ํธํ์ฑ์ด ํ์ํ์ง ์์ ๊ฒฝ์ฐ ๋ฌธ์์ด ํจํด ์ ํ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์๋ฒฝํ๊ณ ์ธ์ฒด๊ณตํ์ ์ ๋๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐ ํธํ์ฑ์ด ํ์ํ ๊ฒฝ์ฐ ๋ฌธ์์ด ํจํด ์ ํ์ด ๊ตฌ์กฐ์ ํ๊ทธ ์ ํ๋ณด๋ค ์ฌ์ ํ ์ข์ต๋๋ค! ๋ด ๋ง์ ๋ค์ด.
๋ชจ๋ธ๋ง๋๋ ๋๋ฉ์ธ์ด ์ ์ดํด๋๋ฉด ์ฌ๋ฌ ๋ช ์ ๊ฒฉ๋ฆฌ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์๊ฐ ๋์ผํ ์ ๊ท์์ ์์ฑํ๊ฒ ๋ ๊ฐ๋ฅ์ฑ์ด ๋งค์ฐ ๋์ต๋๋ค. ๊ตฌ์กฐ์ ํ๊ทธ ์ ํ์ ์ฌ์ฉํ๋ฉด ํ๊ทธ์ ์ํ๋ ์์ฑ๊ณผ ์ ํ์ ๋ชจ๋ ์ธ ์ ์์ต๋๋ค.
๋ชจ๋ธ๋ง๋๋ ๋ชจ๋ ๊ฒ์ ๋ํ ๋ฌธ์์ด ํ์์ ์ง์ ํ๋ ํ์ค ์ด ์๋ ๊ฒฝ์ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์๊ฐ ๋์ผํ ์ ๊ท์์ ์์ฑํ๋ ๊ฒ์ด ๋ณด์ฅ๋ฉ๋๋ค! ๋ค๋ฅธ ์ ๊ท์์ ์์ฑํ๋ฉด ์ค์ ๋ก ํ์ค์ ๋ฐ๋ฅด์ง ์์ต๋๋ค. ๊ทธ๋ค์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์๊ฒ ์ต๋๊น? ๊ตฌ์กฐ์ ํ๊ทธ ์ ํ์ ์ฌ์ฉํ๋ฉด ์ฌ์ ํ ๋ฌด์์ด๋ ์ธ ์ ์์ต๋๋ค. (๋๊ตฐ๊ฐ๊ฐ ๊ด์ฌ์ ๊ฐ์ง ๊ตฌ์กฐ์ ํ๊ทธ ์ ํ ํ์ค์ ์์ํ์ง ์๋ ํ? ใ ใ )
ํ์์ ๊ฐ์ด ๋ช
๋ชฉ ์ ํ์ ๋ฒ์ ๊ฐ ํธํ์ฑ ์ด ๊ฐ์ฅ ๋ฎ ์ต๋๋ค.
์ค, ๋น์ ์ ๋น์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํจ์น ๋๋ ๋ง์ด๋ ๋ฒ์ ์ ๋ถ๋ช์ณค์ต๋๊น?
ํ์ ์ ์ธ์ด ์ฌ์ ํ ๋์ผํฉ๋๊น?
์ฝ๋๋ ์ฌ์ ํ ๋์ผํฉ๋๊น?
์๋์. ๊ทธ๋ค์ ๋ค๋ฅธ ์ ํ์
๋๋ค.
๊ตฌ์กฐ์ ํ๊ทธ ์ ํ์ ํ๊ทธ ์ ํ์ด ๊ตฌ์กฐ์ ์ผ๋ก ๋์ผํ ํ ์ฌ๋ฌ ๋ฒ์ (์ฃผ์ ๋ฒ์ ํฌํจ)์์ ์ฌ์ ํ ํ ๋นํ ์ ์์ต๋๋ค.
๋ฌธ์์ด ํจํด ์ ํ์ regex๊ฐ ๋์ผํ ํ ๋ฒ์ (์ฃผ์ ๋ฒ์ ํฌํจ) ๊ฐ์ ์ฌ์ ํ ํ ๋นํ ์ ์์ต๋๋ค.
์๋๋ฉด ์ ๊ท์์ด ๋์ผํ์ง ํ์ธํ๊ธฐ ์ํด PSPACE-์์ ์๊ณ ๋ฆฌ์ฆ์ ์คํํ ์ ์์ต๋๊น? ์ฐ๋ฆฌ๋ ๋ํ ์ ๊ท์์ ์ด๋ค ํ์ ํด๋์ค๊ฐ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ์ง ๊ฒฐ์ ํ ์ ์์ผ๋ฉฐ ์ด์ ๋ํด ์ต์ ํ๋ ๋ฑ๊ฐ ์๊ณ ๋ฆฌ์ฆ์ ์คํํ ์ ์์ต๋๋ค. ํ์ง๋ง ์ด๋ ๋ง์ ๋ ธ๋ ฅ์ด ํ์ํ ๊ฒ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค.
Regex ํ์ ์ ํ ๊ฒ์ฌ๋ ์์ผ๋ฉด ๋ฉ์ง๊ณ ํ์คํ ๋ฌธ์์ด ํจํด ์ ํ์ ๋ ์ธ์ฒด ๊ณตํ์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ฒ์ ํ์ ์ ํ ๊ฒ์ฌ๊ฐ ์ซ์ ๋ฒ์ ์ ํ ์ ์์ ๋์์ด ๋๋ ๊ฒ์ฒ๋ผ.
[ํธ์งํ๋ค]
์ด ๋๊ธ์์,
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
ํ๋ค๋ฉด ํ
์คํธ๋ฅผ ์คํํ ๋๊น์ง ์ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์๊ฐ ์์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ dogfoodํ ๋ ๋ชจ๋ ๊ณณ์์ as
์ฌ์ฉํ๋ค๋ฉด... ๋ค์ด์คํธ๋ฆผ ์๋น์๋ ์ด๋ป์ต๋๊น? ๊ทธ๋ค์ ๋ํ ๋ชจ๋ ๊ณณ์์ as
๋ฅผ ์ฌ์ฉํ๊ณ ์ ๋ฒ์ ์ผ๋ก ์
๊ทธ๋ ์ด๋ํ ๋ ๋ฐํ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์๊น์?
๋ฌธ์์ด ํจํด ์ ํ์ ์ฌ์ฉํ๋ฉด ๋ชจ๋ ๊ณณ์์ as
๋ฅผ ์ฌ์ฉํ ์ด์ ๊ฐ ์ค์ด๋ค๊ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์์ ๋ค์ด์คํธ๋ฆผ ์๋น์ ๋ชจ๋ ๋ณ๊ฒฝ ์ฌํญ์ ๊นจ๋ ๊ฒ์ ๋ ์ฝ๊ฒ ์ ์ ์์ต๋๋ค.
(์ฅํฉํ์ง๋ง ๋ด ์์ ์ค ์ผ๋ถ๊ฐ ํต๊ณผ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.)
๋ํ ๋๋ ๋ง์ ์ปดํ์ผ ํ์ ํ ์คํธ๋ฅผ ์์ฑํฉ๋๋ค(TS ํ๋ ๊ทธ๋ ๊ฒ ํ๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค).
ํน์ string
๋ฆฌํฐ๋ด์ด ๋ด ์ปดํ์ผ ํ์ ํ
์คํธ์์ ์ ๊ท์ ๊ฒ์ฌ์ ์คํจ/ํต๊ณผํ๋์ง ํ
์คํธํ ์ ์๋ค๋ฉด ์ข์ ๊ฒ์
๋๋ค. ํ์ฌ๋ก์๋ ์ด๋ฌํ ๊ฒ๋ค์ ๋ํ ์ปดํ์ผ ํ์ ํ
์คํธ๋ฅผ ํ ์ ์์ผ๋ฉฐ ๋์ ๋ฐํ์ ํ
์คํธ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ์ด ๋ด ์ปดํ์ผ ์๊ฐ ํ ์คํธ์ ์คํจ/ํต๊ณผํ๋ฉด ๋ค์ด์คํธ๋ฆผ ์๋น์๊ฐ ํด๋น ๋ฌธ์์ด ๋ฆฌํฐ๋ด(๋๋ ์ ์ฌํ ๋ฌธ์์ด)์ ์ฌ์ฉํ๊ณ ์ฌ๋ฐ๋ฅธ ๋ฐฉ์์ผ๋ก ์๋ํ ๊ฒ์ผ๋ก ๊ธฐ๋ํ ์ ์๋ค๋ ํ์ ์ ๊ฐ๊ฒ ๋ฉ๋๋ค.
์ด๋ฌ๋ค ๋ฐ๋ฒจํ ์ฌํ๋ก ์์๊ฐ์ ํ๋ฌ๊ฐ๋ ๊ฒ ๊ฐ์๋ฐ...
์ด๊ฒ์ ์ค์ ๋ก ๋ช ๋ชฉ/๊ตฌ์กฐ ํ๊ทธ ์ ํ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์ ๋์ฑ ๊ทธ๋ ์ต๋๋ค. ์์ ์์์ ์ ์ ์๋ฏ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐ/๋ฒ์ ํธํ์ฑ์ด ๋์ฐํฉ๋๋ค...
๊ทธ๋ฌ๋ regexes/string-pattern ์ ํ์ ํด๋น ๋ฌธ์ ์ ๋น ์ง์ง ์์ ์ ์ ํ ๊ธฐํ ๊ฐ ์์ต๋๋ค(ํ์คํ ๋ฐ ์ ์์ ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์ ๋๋ถ์).
์ค๋ ๋์์ ์ผ๋ฐ์ ์ธ ๊ฒ์ ์ด๋ฌํ ์ ๊ท์์ด ํ ์คํธ ์ฝ๋์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ ๋ฐ ๋์์ด ๋๋ค๋ ๊ฒ์ ๋๋ค. ํ๋ก๋์ ์๋๋ฆฌ์ค์์ ์ฝ๋๊ฐ ํ๋์ฝ๋ฉ๋ ๋ฆฌํฐ๋ด์ด ์๋ ๋ฐํ์ ์ ๊ณต ๋ฌธ์์ด์ ๋ํด ์คํ๋๋๋ผ๋ ํ ์คํธ ๋ฌธ์์ด์ด " ์ณ์". ์ด๊ฒ์ ๋์ ์ ๋ช ๋ชฉ/ํ๊ทธ/๋ธ๋๋ ๋ฌธ์์ด์ ๋ํ ์ธ์๋ก ๋ณด์ผ ์ ์์ต๋๋ค. ์๋ํ๋ฉด ์ ํจ์ฑ ๊ฒ์ฌ ๊ธฐ๋ฅ์ ์ด๋ ์ชฝ์ด๋ ์์ฑํ๊ณ ํ ์คํธ์ ์ด์ ์ ์ฒ ์ ํ๊ฒ ์คํ๋๋ค๋ ๊ฒ์ ์ ์ ์๋ค๋ ๊ฒ์ ๋๋ค(๋ฐ๋ผ์ ํ ์คํธ ์ ๋ ฅ์ ๋ชจ๋ ์ค๋ฅ๋ ๊ฐ๋ฐ ์ฃผ๊ธฐ ์ด๊ธฐ์ ํ๋๊ทธ ์ง์ ).
์... ์ด ๊ธ์ ์ฐ๊ธฐ ์ ์ ๋จผ์ ๋ค ์ฝ์์ด์ผ ํ๋๋ฐ...
์ด์จ๋ ๋ฌธ์์ด ํจํด ์ ํ์ด ์ ์ฉํ ๋ช ๊ฐ์ง ์๊ฐ ์์ต๋๋ค.
์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ 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 ๊ฒฝ๋ก์์ ?
๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ๋ง์ง ์์ต๋๋ค.
๋๋ ๋น์ ์ด ์ด๋ฏธ ์ด ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์๊ณ ์๋ค๋ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค.
์ด ์ค๋ ๋๋ ๋ค์ํ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์๋ฏธํฉ๋๋ค. ๊ตฌ์ฒด์ ์ธ ์๋ ๋ ๋๋ฌผ์๋ค. ๋ฌธ์ ๋ ์ด๋ฌํ ์์ ์ค ๋ง์ ๋ถ๋ถ์ด ์์ ํ์ง ์๋ค๋ ๊ฒ์ ๋๋ค. ์ ํจํ ์ ๋ ฅ์ ๊ฑฐ๋ถํ๋ RegExp๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋ฐ๋ผ์ ์ ์๋ ๋ง์ ์ ๊ท์์ "์๋ฒฝ"ํ์ง ์์ต๋๋ค.
ํ์ง๋ง ์ ํจํ ์
๋ ฅ์ ๊ฑฐ๋ถํ์ง ์๋ ํ ๊ด์ฐฎ๊ฒ ์ฃ ?
์๋ชป๋ ์
๋ ฅ์ ํ์ฉํด๋ ๊ด์ฐฎ์ต๋๋ค. ๊ทธ๋ ์ฃ ?
๋ฐํ์ ๋์ "์ค์ " ํ์๋ฅผ ๊ฐ์ง ์ ์๊ธฐ ๋๋ฌธ์ ์ ์ฒด ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ปดํ์ผ ์๊ฐ ๊ฒ์ฌ๋ ๋ค์ด์คํธ๋ฆผ ์ฌ์ฉ์์ ์ผ๋ฐ์ ์ธ ๋ฌธ์ ๋ฅผ ๋ง์ด ์ ๊ฑฐํ์ฌ ์์ฐ์ฑ์ ๋์ผ ์ ์์ต๋๋ค.
์ ํจํ ์ ๋ ฅ์ ๊ฑฐ๋ถํ๋ ์์ ๋ ์์ ํ๊ธฐ ์ฌ์์ผ ์ ํจํ ์ ๋ ฅ์ ๊ฑฐ๋ถํ์ง ์์ง๋ง ์๋ชป๋ ์ ๋ ฅ์ ํ์ฉํฉ๋๋ค.
์ด์จ๋ ๋ฌธ์์ด ํจํด ์ ํ์ ๊ต์ฐจ ์ ํ์ ๋งค์ฐ ์ ์ฉํ ๊ฒ์ ๋๋ค!
๋ด .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
์ ๊ฑฐ์ ๋์ผํ๋ฉฐ ๋ฐํ์ ๊ฒ์ฌ๋ฅผ ์ํด ๋ง์ ์ ํ ์์ ์ ์ ๊ฑฐํ๊ณ ์๋นํ๋ ๊ฐ๋ฐ์์๊ฒ ๋ถํธ์ ์ค๋๋ค.
์ธ๊ธ๋ ์ผ๋ถ ์ฌ์ฉ ์ฌ๋ก์ ๊ฒฝ์ฐ Regex์ ์์ ํ์ ์งํฉ๋ง ํ์ํฉ๋๋ค(์: ์ ๋์ฌ ์ผ์น).
์ ์ฌ์ ์ผ๋ก ์ด๊ฒ์ Variadic Kinds #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;
์ธ๊ธ๋ ์ผ๋ถ ์ฌ์ฉ ์ฌ๋ก์ ๊ฒฝ์ฐ Regex์ ์์ ํ์ ์งํฉ๋ง ํ์ํฉ๋๋ค(์: ์ ๋์ฌ ์ผ์น).
๋๋ ์ฌ์ ํ ์ด + ๋ช ๊ฐ์ง ๋ค๋ฅธ ๊ฒ๋ค์ ์ ๊ณตํ๋ ๋ด ์ ์ ์ ์ง์งํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ๋ณ์ด ์๋ ์ธ์ด ์ ์์ฃผ ์์ ์์ ์งํฉ์ ์ฌ์ ํ โโํฉ๋ฆฌ์ ์ผ๋ก ํจ์จ์ ์ผ๋ก ๋ถ๋ถ ์งํฉ๊ณผ ํ๋ฑ์ ํ์ธํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ง๊ธ๊น์ง TS ํ์ ๊ฐ์ฅ ํฐ ์ฐ๋ ค์ธ ์์ ์ ๊ท์์ ์ฑ๋ฅ ์ธก๋ฉด์ ํด๊ฒฐํ๋ ค๋ ๋ค๋ฅธ ์ ์์ ๋ณธ ์ ์ด ์์ต๋๋ค.
๋ณํ ์๋ ์ธ์ด์ ๋ฌธ์ ๋ ์ด๋ฆ์์ ์ ์ ์๋ฏ์ด ๋ณํ๋ฅผ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ URL๊ณผ ๊ฐ์ ํญ๋ชฉ์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๊ธฐ ์ด๋ ต์ต๋๋ค. ๊ฒ๋ค๊ฐ ๋๋ถ๋ถ์ ์ฌ๋๋ค์ ๋ณ์ ์ํ ๊ฒ์ด๊ณ ์์์ ์์ ๋ฐ๋ณต ์ํ์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ณ์ ์๋ฎฌ๋ ์ดํธํ๋ฏ๋ก ํ์ ์งํฉ์ ํ์ธํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋๋ถ๋ถ์ ์ผ๋ฐ DFA ํํ ๊ฐ๋ฅ ์ ๊ท์์ ์ฑ๋ฅ์ ๊ทธ๋ ๊ฒ ๋์์ง ์์ผ๋ฉฐ ํ์/์์ ์งํฉ์ ๋ํด ์ด๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
๊ทธ๋๋ ์ผ์ข
์ *
์ ์ป์ ์ ์์ต๋๋ค.
const str : PatternOf</ab+c/> | PatternOf</ac/>
@TijmenW ๋ด ์ ์์ ์กฐ๊ธ ๋ ์์ธํ ์ฝ์ผ์ญ์์ค. ์จ๊ฒจ์ง ๊ทผ๊ฑฐ์ ์ค์ ๋ก ์ค์ฉ์ ์ผ๋ก ๋ง๋๋ ๋ช ๊ฐ์ง ์์ ๊ธฐ๋ฅ์ด ์์ต๋๋ค. ๋ณํ ์๋ ๋ฌธ๋ฒ์ ์ง์ ํ๋ ๋ฐ ์ง์ ์ ์ผ๋ก ์ ํ๋์ง๋ ์์ง๋ง ๋ด ์ค๊ณ ๊ธ ์ฌ์ฉ ์ฌ๋ก์ ์ค์ง์ ์ผ๋ก ์ ์ฉํ ๋งํผ๋ง ํ์ฅ๋ ์์ ์์ ์งํฉ์
๋๋ค. ํนํ, ๊ฐ๋ณ ๋ฌธ์์ ๋ํด starof ('a' | 'b' | ...)
๋ฅผ ์ํํ ์ ์๊ณ string
์ ๋๋ฑํ๊ฒ starof UnionOfAllCodePoints
(์ฌ์ค์ ์ด๋ก ์ ๋ ์ด์ ๊ธฐ๋ณธ ์์๊ฐ ์๋).
๋ํ ์ ๊ท ์ธ์ด๊ฐ ๋ค๋ฅธ ์ ๊ท ์ธ์ด์ ์ผ์นํ๋ ๋ถ๋ถ ์งํฉ๊ณผ ์ผ์นํ๋์ง ํ์ธํ๋ ๊ฒ์ NP-์์ ํ๊ณ ์ผ๋ฐ ํ์ ๊ทธ๋ํ ๋ํ ๋ฌธ์ ์ ๋์ผํฉ๋๋ค. ์ด๊ฒ์ด ๋ฐ๋ก ํ์ค ์ ๊ท ์ธ์ด๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ด์ ์ด๋ฉฐ, ์ด๋ก ์ ๊ณ์ฐ ๋ณต์ก์ฑ์ ๋ฎ์ถ๊ธฐ ์ํด ๊ฐ๋ฅํ ํ starof
๋ฅผ ์ ํํ๋ ค๊ณ ํ ์ด์ ์
๋๋ค.
TODO: RegExp ์ ํ์ ์ด์ ์ ์ป์ ์ ์๋ ์ค์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์์ ์ฌ์ฉํ ์ค์ ํํ์์ ์๋ณํ์ฌ ์ ํฌ๋ฅผ ๋์์ฃผ์ธ์.
์ด๊ฒ์ ์์ ํ ์๋ก์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๊ธฐ ๋๋ฌธ์ ์ฝ๊ฐ์ ์ ๋ณด๋ก ๋ฐ์๋ค์ผ ์ ์์ง๋ง https://github.com/ostrrowr/ts-json-validator ์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ ๊ท์ ์ ํ๊ณผ ๊ฐ์ ๊ฒ์ผ๋ก ํจ์ฌ ๋ ์ ์ฉํ ๊ฒ์ ๋๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ชฉํ๋ ๋ค์๊ณผ ๊ฐ์ Typescript ์ ํ/JSON ์คํค๋ง ์ <T, s>
์ ์์ฑํ๋ ๊ฒ์
๋๋ค.
s
๊ฒ์ฆํ๊ธฐ ์ํด ํ ๋น ํ ์ ์์ต๋๋ค T
T
ํ ๋นํ ์ ์๋ ๊ฐ๋ฅํ ํ ์ ์ ์ ํ์ด s
์ ๋ํด ์คํ๋ ๋ ์ ํจ์ฑ ๊ฒ์ฌ์ ์คํจํฉ๋๋ค.์ ๊ท์ ์ ํ์ ๊ฒ์ฆ๋ ์ ํ์ด ์ต์ํ ๋ค์ ํค์๋์ ๋ํด ๋ ์๊ฒฉํ๋๋ก ํ์ฉํ์ฌ (2)์ ์๊ฒฉ์ฑ์ ๊ฐ์ ํฉ๋๋ค.
format
patternProperties
propertyNames
TODO: RegExp ์ ํ์ ์ด์ ์ ์ป์ ์ ์๋ ์ค์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์์ ์ฌ์ฉํ ์ค์ ํํ์์ ์๋ณํ์ฌ ์ ํฌ๋ฅผ ๋์์ฃผ์ธ์.
๋ชจ๋ Excel ์ธํฐํ์ด์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ A1
๋๋ A5:B7
ํ์ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์์ฑ ํค / ์ ๊ท์ ๋ฌธ์์ด ์ธ๋ฑ์
์ผ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์์ฑ ์ด๋ฆ์ ๋ฐ๋ผ ๊ฐ์ฒด๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์๋ฅผ ๋ค์ด React์์ ์ด๋ฆ์ด
aria-
์์ํ๋ ๋ชจ๋ ์ํ์ ์ ํ์ ์ ์ฉํ๋ ค๊ณ ํฉ๋๋ค.interface IntrinsicElements { // .... [attributeName: /aria-\w+/]: number | string | boolean; }
์ด๊ฒ์ ์ฌ์ค์ ์ง๊ต ๊ฐ๋ ์ ๋๋ค(Regex ์์ฑ ํค๋ฅผ ์ถ๊ฐํ์ง ์๊ณ Regex ์ ํ์ ์ถ๊ฐํ ์ ์์ผ๋ฉฐ ๊ทธ ๋ฐ๋์ ๊ฒฝ์ฐ๋ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค).
๋๋ ์ด๊ฒ์ด ์ฌ๊ธฐ์ ์งํ๋๋ ๋ชจ๋ ๊ฒ๊ณผ ์ฝ๊ฐ ์ง๊ตํ๋ค๋ ๊ฒ์ ์๊ณ ์์ง๋ง Wesley๋ ๋น์ ์ด ์ฐ๋ฆฌ์ ์
๋ ฅ์ ์ฌ์ฉํ ์ ์๋ค๊ณ ์๊ฐํ์ต๋๋ค. ์ด๊ฒ์ ์ฌ๋ฌ ๊ฐ์ง ์ด์ ๋ก Fabric์์ ๊ณ์ ๋ํ๋ฉ๋๋ค. ์ปดํฌ๋ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก์ ์ฐ๋ฆฌ๋ data-
๋ฐ aria-
์์ฑ์ ํฌํจํ์ฌ TypeScript์์ ํ์ฉํ๋ React ์ปดํฌ๋ํธ ์ธํฐํ์ด์ค๋ฅผ ์ ํํ๊ฒ ๋ฐ์ํ๋ ์ปดํฌ๋ํธ props ์ธํฐํ์ด์ค๋ฅผ ํฅ์์ํฌ ์ ์๊ธฐ๋ฅผ ์ํฉ๋๋ค. ๊ทธ๊ฒ ์์ด๋ ์ด๋ฌํ ์์ฑ์ ์ฌ์ฉํ ์๋น์ ์๊ฒ
์ฐ๋ฆฌ๊ฐ ๋์ธ ์ ์๋ ์ผ์ด ์๋ค๋ฉด ์๋ ค์ฃผ์ธ์! ๐
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 ์ ํ์ ์ด์ ์ ์ป์ ์ ์๋ ์ค์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์์ ์ฌ์ฉํ ์ค์ ํํ์์ ์๋ณํ์ฌ ์ ํฌ๋ฅผ ๋์์ฃผ์ธ์.
ํฌ๋ก ์์ . (์ด๊ฒ์ ์ธ๊ธ๋์ง ์์ ๊ฒ์ ๋งค์ฐ ๋๋์ต๋๋ค)
^((\*|\d+((\/|\-|,){0,1}(\d+))*)\s*){6}$
์ฌ๊ธฐ์ 2์ผํธ๋ง ํฌ์ํ๋ฉด ๋ฉ๋๋ค. ์ ๋ HTML id
์์ฑ์ผ๋ก ์ฌ์ฉ๋ ์ํ์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ ค๋ React ํ๋ก์ ํธ์์ ์์
ํ๊ณ ์์ต๋๋ค. ์ฆ, ๋ค์ ๊ท์น์ ์ถฉ์กฑํด์ผ ํ๋ฉฐ ๊ทธ๋ ์ง ์์ผ๋ฉด ์๊ธฐ์น ์์ ๋์์ด ๋ฐ์ํฉ๋๋ค.
๋ค์ ๋งํด:
interface Props {
id: PatternOf</[^ ]+/>;
}
๋ ๋ค๋ฅธ ์: '<namespace>/<name>[@<version>]'
ํ์์ผ๋ก ์์๋๋ ๋ฌธ์์ด์ด ์๋ ์ฑ์ญ ์ ํ ์๋ณ์
์ฌ์ฉ ์ฌ๋ก: Navigator.registerProtocolHandler()
์ ๊ฐ์ ๋ฌธ์์ด ํ์ DOM API
MDN ์ธ์ฉ:
๋ณด์์์ ์ด์ ๋ก
registerProtocolHandler()
๋ ๋ฑ๋กํ ์ ์๋ ์ฒด๊ณ๋ฅผ ์ ํํฉ๋๋ค.๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ ์ฌ์ฉ์ ์ง์ ์ฒด๊ณ๋ฅผ ๋ฑ๋กํ ์ ์์ต๋๋ค.
- ์ฌ์ฉ์ ์ ์ ๊ตฌ์ฑํ์ ์ด๋ฆ์
web+
- ๋ง์ถค ๊ตฌ์ฑํ์ ์ด๋ฆ์๋
web+
์ ๋์ฌ ๋ค์ ํ๋ ์ด์์ ๋ฌธ์๊ฐ ํฌํจ๋ฉ๋๋ค.- ์ฌ์ฉ์ ์ ์ ๊ตฌ์ฑํ๋ ์ด๋ฆ์ ์๋ฌธ์ ASCII ๋ฌธ์๋ง ์์ต๋๋ค.
์ฆ, Navigator.registerProtocolHandler()
๋ ์ ์๋ ค์ง string
๋๋ ์ฌ์ฉ์ ์ ์ string
์์ํ์ง๋ง ํน์ ์คํค๋ง๋ฅผ ์ค์ํ๋ ๊ฒฝ์ฐ์๋ง ๊ฐ๋ฅํฉ๋๋ค.
CSSType ์ ๋ํ CSS ์ฌ์ฉ์ ์ ์ ์์ฑ์ --
์ ๋์ฌ๊ฐ ๋ถ์ ์์ฑ์ ์ ์ธํ ๋ชจ๋ ์์ฑ์ ๋ํด ๋ซํ ์ ํ์ ์ ๊ณตํ๋ ๋ ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก์
๋๋ค.
interface Properties {
// ....
[customProperty: /--[a-z][^\s]*/]: number | string;
}`
์ด๊ฒ์ด ๊ตฌ์ฒดํ ์ ํ๊ณผ ๋์ผํ์ง ๋๊ตฐ๊ฐ ๋งํด ์ค ์ ์์ต๋๊น? https://github.com/microsoft/TypeScript/issues/7599
@gautam1168 ์ด๋ก ์ ์ผ๋ก ๋ฌธ์์ด ์ ํ์ ๊ตฌ์ฒด์ ์ผ๋ก ๊ตฌ์ฒดํํ๋ ๋ถ๋ถ ์งํฉ์ ๋๋ค. (๋ฌผ๋ก ์ซ์ ์ ํ์๋ ๊ณ ์ ํ ๊ด์ฌ์ฌ๊ฐ ์์ต๋๋ค.)
์ธ๊ธ๋ ์ผ๋ถ ์ฌ์ฉ ์ฌ๋ก์ ๊ฒฝ์ฐ Regex์ ์์ ํ์ ์งํฉ๋ง ํ์ํฉ๋๋ค(์: ์ ๋์ฌ ์ผ์น).
๋๋ ์ฌ์ ํ ์ด + ๋ช ๊ฐ์ง ๋ค๋ฅธ ๊ฒ๋ค์ ์ ๊ณตํ๋ ๋ด ์ ์ ์ ์ง์งํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ๋ณ์ด ์๋ ์ธ์ด ์ ์์ฃผ ์์ ์์ ์งํฉ์ ์ฌ์ ํ โโํฉ๋ฆฌ์ ์ผ๋ก ํจ์จ์ ์ผ๋ก ๋ถ๋ถ ์งํฉ๊ณผ ํ๋ฑ์ ํ์ธํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ง๊ธ๊น์ง 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
๋ํ ๋ ๋์ ๋์์ ์ฐ์ฐ์๋ก ์ฌ์ฉํ์ฌ ๊ทธ๋ฐ ์ข
๋ฅ์ ๊ฒ์ ๋ชจ๋ธ๋งํ๊ณ ์ถ์ต๋๋ค.
๊ถ๊ธํฉ๋๋ค. ์ ๊ท์์ ํฌํจ/ํฌํจ์ ๊ฒฐ์ ํ ์ ์์ต๋๊น? Wikipedia์ ๋ฐ๋ฅด๋ฉด ๊ฒฐ์ ๊ฐ๋ฅํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๊ฒ์ด JS์ ์ ๊ท ํํ์๋ ์ค๋ช
ํฉ๋๊น? ํ์ค RE(์: ์ญ์ฐธ์กฐ)๋ณด๋ค ๋ ๋ง์ ๊ธฐ๋ฅ์ด ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ฒฐ์ ๊ฐ๋ฅํ๋ค๋ฉด ๊ณ์ฐ์ ์ผ๋ก ์คํ ๊ฐ๋ฅํ๊ฐ?
์ด๊ฒ์ ์ด ๊ธฐ๋ฅ์ ์ํฅ์ ๋ฏธ์นฉ๋๋ค(์ขํ๊ธฐ):
if (Gmail.test(candidate)) {
// candidate is also an Email
}
@nikeee Decidable์ ์ด๊ฒ์ด ํ์ค์ ์ด๊ธฐ์ ์ถฉ๋ถํ์ง ์์ต๋๋ค. 2์ฐจ ์๊ฐ์กฐ์ฐจ๋ ์ผ๋ฐ์ ์ผ๋ก ์ด ๊ท๋ชจ์์ ๋๋ฌด ๋๋ฆฝ๋๋ค. TS๋ ์๋์ง๋ง ๋น์ทํ ๋ฌธ์ ์ ๋ํ ๋ฐฐ๊ฒฝ ์ง์์ด ์์ต๋๋ค.
์ญ ์ฐธ์กฐ์ ์ง๋ฉดํ์ฌ ์ฌ์ ํ ๊ฒฐ์ ๊ฐ๋ฅํ์ง๋ง ๋ ๋์์ง๋ ์๋๋ผ๋ ๊ธฐํ ๊ธ์์ ์ผ ๊ฐ๋ฅ์ฑ์ด ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ค๋ง, ๊ต์ก๋ฐ์ ์ถ์ธก์ผ ๋ฟ์ ๋๋ค.
์ด๊ฒ์ ๋ช ํํ ํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค!
2์ฐจ ์๊ฐ์กฐ์ฐจ๋ ์ผ๋ฐ์ ์ผ๋ก ์ด ๊ท๋ชจ์์ ๋๋ฌด ๋๋ฆฝ๋๋ค.
์ด๊ฒ์ด ๋ด๊ฐ ๊ณ์ฐ์ ์ผ๋ก ์คํ ๊ฐ๋ฅํ์ง ๋ฌผ์ ์ด์ ์ด๊ธฐ๋ ํ๊ณ , ๊ทธ๋์ ๋๋ ๊ทธ๋ ์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํ๋ฑ์๋ ๋์ผํ๊ฒ ์ ์ฉ๋๋ค๋ฉด ์ด ๊ธฐ๋ฅ์ ๊ฑฐ์ ๋ชจ๋ ์์ฑ์ด ์คํ ๋ถ๊ฐ๋ฅํ์ง ์์ต๋๊น? ์ ๊ฐ ํ๋ ธ๋ค๋ฉด ์ ์ ํฉ๋๋ค๋ง, ๋จ์ ๊ฒ์ ํ์๊ฐ์ ๋ฟ์ธ ๊ฒ ๊ฐ์ต๋๋ค. ์ด๊ฒ๋ง์ผ๋ก๋ ์ ์ฉํ์ง ์์ ๊ฒ ๊ฐ์์.
@nikeee ์ด ํจํด์ ๋ฌธ์ ๊ทธ๋๋ก ๋น๊ต ๋์์ด ๋๋ ๋ชจ๋ ์ ํ์ ๋ชจ๋ ์์ฑ์ ๋ํด ๊ฒ์ฌ๋๋ค๋ ์ ์ ์ผ๋์ ๋ ๊ฐ์น๊ฐ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ regexp ์์ฑ์ด ์๋ ์ ํ์ ๊ฒฝ์ฐ regexp๊ฐ ๊ทธ ์์ฒด๋ก ๋ค์ ๋ณต์กํ ์ง์น์ธ ๋ค๋ฅธ regexp์ ์ผ์นํ๋ ํ์ ์งํฉ๊ณผ ์ผ์นํ๋์ง ์ฌ๋ถ๋ฅผ ๊ณ์ฐ ํด์ผ ํฉ๋๋ค.
๋ถ๊ฐ๋ฅํ ๊ฒ์ด ์๋๋ผ ์ด๋ ค์ธ ๋ฟ์ด๋ฉฐ ์คํ ๊ฐ๋ฅํ๋ ค๋ฉด ์ ํ์ ์ด์ด์ผ ํฉ๋๋ค. (์๋ฅผ ๋ค์ด, JS regexps๋ ์๋ํ์ง ์์ ๊ฒ์ ๋๋ค. ํ์ฅ ๊ฐ๋ฅํ์ง ์์ ๋ฟ๋ง ์๋๋ผ ๋๋ฌด ์ ์ฐํฉ๋๋ค.)
ํธ์ง: ๋๋ ์ด๊ฒ์ ๋ํ์ดํ๊ณ ์ถ์ต๋๋ค: ์ ๋ ๋ช ํํ ํ๊ธฐ ์ํด TS ํ์ ์์ง ์์ต๋๋ค . CS ์๊ณ ๋ฆฌ์ฆ ์ค๊ณ์ ๋ํ ๋ฐฐ๊ฒฝ ์ง์์ด ์์ต๋๋ค.
ํ , ๊ทธ๋์ "์ผ๋ฐ์ ์ธ" RegEx์ "์ ํ๋" ํ์ ์งํฉ๋ง ์ง์ํ ์ ์์ต๋๋ค. ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๊ฐ์ํ ๋ ์ ๊ท์์ ์ง๊ธ๊น์ง ๋งค์ฐ ๊ฐ๋จํ์ต๋๋ค. (์์, ์ ํ ๋ฒํธ ๋ฑ)
ํ์ ์งํฉ๋ง ์ง์ํ๋ 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}`
(์ด๊ฒ์ ๊ตฌํ์์ ๊ณต์ฉ์ฒด ์ ํ์ ์ฌ์ฉํ๋ค๊ณ ๊ฐ์ ํฉ๋๋ค. ๋ค๋ฅธ/๋ ๋ณต์กํ ๊ตฌํ์์ ์๋ํ ์ ์์)
๋ฉด์ฑ ์กฐํญ: ์ ๋ TS ํ์ ์ผ์์ด ์๋๋ฉฐ TS์์ ์ผํ๊ณ ์์ง ์์ต๋๋ค. ๊ทธ๋ฅ ๋ด 2c.
@rozzzly @nikeee ๋ช ๊ฐ์ง ์์ ๊ธฐ๋ฅ์ด ๋๋ฝ๋ ๊ฒ์ด ์ ์ ์์ ํต์ฌ์ ๋๋ค . ๋๋ ์ ๊ท์ ๋ฆฌํฐ๋ด ๋ฑ์ ์๋ฏธ์์ ์ ๊ท์์ด ์๋ ์ ๊ท ์ธ์ด์ ํฐ ๋ถ๋ถ ์งํฉ(๊ณต์ ์ธ์ด ๊ฐ๋ )์ ๊ธฐ๋ฐ์ผ๋ก ํ๊ธฐ ๋๋ฌธ์ ๊ทธ๋ณด๋ค ํจ์ฌ ๋ ๊ฐ๋ ฅํ์ง๋ง ์์ ์ ์๋ฃํ ๋งํผ ์ถฉ๋ถํ ๊ฐ๋ ฅํฉ๋๋ค.
์ด ์ ๊ทผ ๋ฐฉ์์ด ๋ ์ฌ์ฉ์ ์นํ์ ์ผ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ ํ์ ๋ํ ์ฐ์ ์ฐ์ฐ์ ํด๋นํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ํ์ ์ ํ์ด ๋ค๋ฅธ ์ ํ์ ํ์ ์ ํ์ธ์ง ์ฌ๋ถ๋ฅผ ํ์ธํ๋ ๊ฒ์ ์ฃผ์ด์ง ํ์ ์ธ์ด์ ๋ฌธ์์ด์ด ํฌํจ๋์ด ์๋์ง ํ์ธํ๋ ๊ฒ๊ณผ ๊ณ์ฐ์ ์ผ๋ก ๋์ผํ๋ค๊ณ ๋งํฉ๋๋ค.
ํนํ ๋๋ฉ์ธ ์ ํจ์ฑ ๊ฒ์ฌ๋ TLD/ ๊ณต๊ฐ ์ ๋ฏธ์ฌ ์ ํจ์ฑ๋ ํ์ธํ๋ ๊ฒฝ์ฐ ์ค์ ๋ก ์ํํ๊ธฐ ๋งค์ฐ ๋ณต์กํ ์์
์
๋๋ค. RFC์ ๋ฐ๋ฅธ ์ผ๋ฐ ๋๋ฉ์ธ ์์ฒด๋ /[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)+/
+ ์ต๋ 255์๋งํผ ๊ฐ๋จํ์ง๋ง, ์์ ์ ๊ท ํํ์์์ ๋ณด์ฌ์ฃผ๋ฏ์ด ์ ์ฒด ์ผ๋ฐ ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ง ์๋ ํ ์ด๋ง์ ๋ ์
๋ ฅํ๊ธฐ๊ฐ ๋งค์ฐ ๋ณต์กํฉ๋๋ค. @rozzzly ๋๋ ๋ด ์ ์์ ๋ฌธ์์ด๋ง ์ฌ์ฉํ์ฌ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ๋งค์ฐ ๊ฐ๋จํ๊ฒ ์ ํ์ ์์ฑํ ์ ์์ง๋ง(๋
์์๊ฒ ์ฐ์ต์ฉ์ผ๋ก ๋จ๊ฒจ๋๊ฒ ์ต๋๋ค) ์ต์ข
๊ฒฐ๊ณผ๋ ์ฌ์ ํ ๋ค์ ๋ณต์กํฉ๋๋ค.
@isiahmeadows
๊ทธ๊ฒ์ ๋ช ๊ฐ์ง ์์ ๊ธฐ๋ฅ์ด ๋น ์ง
์ด ์ ์ฒด ์ค๋ ๋๋ฅผ ๋ง์ง๋ง์ผ๋ก ์ฝ์ ๊ฒ์ 1๋ ์ด ํจ์ฌ ๋์์ต๋๋ค. ์ฌ๋ ์๊ฐ์ ์๋ฆผ์ ๋ณด๊ณ @rugk๋ ์ _"๊ธ์ ... "์ ๊ท์"์ด๋ผ๊ณ ๋ถ๋ฅด์ง ๋ง์ธ์ -
...์์ regexp๊ฐ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ฒ๋ผ ์์ ํ ์ ๊ท ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ง ์๋ ํ ์ด๊ฒ์ ์ ๋ ฅํ๊ธฐ๊ฐ ๋งค์ฐ ๋ณต์กํฉ๋๋ค. @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 ์ฌ์ด์ ์ ์"(๋ฉ์์ง ๋ฒํผ ํ ๋น ๊ธธ์ด๋ฅผ ์๊ฐํจ)๋ผ๋ ๋ฒ์๋ฅผ ๋ฒ์ด๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผ๋๋ ๊ฒฝ์ฐ ์ด ๋ฌธ์ ๊ฐ ํ์ฌ typescript์์ ์๋ฏธ๊ฐ ์๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
@simonbuchan ์ต์ํ ์ ๋์ฌ์ ์ ๋ฏธ์ฌ ์ ํ์ด ์กด์ฌํด์ผ ํฉ๋๋ค. ์ด๋ ๋ง์ DOM ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ๋ ์์ํฌ์ ํ์ํฉ๋๋ค.
๋๋ ์ด๊ฒ์ด ์ฃฝ๋๋ก ๋๋ค๊ฒจ ๋ง์๊ณ ๋ช ๊ฐ์ง ์ข์ ์ ์์ด ์ด๋ฏธ ์ฃผ์ด์ก๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ์ผ๋ถ ์ฌ๋๋ค์ด ์ฝ๊ฐ ํฅ๋ฏธ๋กญ๊ฒ ์๊ฐํ ์ ์๋ ์ถ๊ฐ ํญ๋ชฉ์ ์ถ๊ฐํ๊ณ ์ถ์์ต๋๋ค.
์ญ ์ฐธ์กฐ์ ์ง๋ฉดํ์ฌ ์ฌ์ ํ ๊ฒฐ์ ๊ฐ๋ฅํ์ง๋ง ๋ ๋์์ง๋ ์๋๋ผ๋ ๊ธฐํ ๊ธ์์ ์ผ ๊ฐ๋ฅ์ฑ์ด ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ค๋ง, ๊ต์ก๋ฐ์ ์ถ์ธก์ผ ๋ฟ์ ๋๋ค.
์ญ ์ฐธ์กฐ๋ regexp๊ฐ ์ปจํ ์คํธ ํ๋ฆฌ ๋ฌธ๋ฒ์ ์์ ์งํฉ์ธ ์ปจํ ์คํธ์ ๋ฏผ๊ฐํ ๋ฌธ๋ฒ์ โโ์ค๋ช ํ๋๋ก ๋ง๋ค ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ CFG์ ๋ํ ์ธ์ด ํ๋ฑ์ ๊ฒฐ์ ํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ ํ ์ ํ ์๋ ์ฅ์น์ ํด๋นํ๋ CSG์ ๊ฒฝ์ฐ ๋ ๋์ฉ๋๋ค.
DFA๋ก ๋ณํํ ์ ์๋ ๋ชจ๋ ์ ๊ท ํํ์์ด ์ ๊ท ํํ์(concat, union, star, ๊ต์งํฉ, ๋ณด์ ๋ฑ)์ ์ฌ์ฉ๋๋ค๊ณ ๊ฐ์ ํ๋ฉด ์ ๊ท ํํ์์ NFA๋ก ๋ณํํ๋ ๊ฒ์ O(n)์ด๋ฉฐ 2์ ๊ณฑ์ ์ป์ต๋๋ค. NFA๋ O(m*n)์ด๊ณ ์๋ฝ ์ํ์ ๋ํ ๊ฒฐ๊ณผ ๊ทธ๋ํ๋ฅผ ์ํํ๋ ๊ฒ์ O(m*n)์ ๋๋ค. ๋ฐ๋ผ์ ๋ ์ ๊ท ์ ๊ท์์ ์ธ์ด ๋๋ฑ์ฑ/๋ถ๋ถ์งํฉ์ ํ์ธํ๋ ๊ฒ๋ O(m*n)์ ๋๋ค.
๋ฌธ์ ๋ ์ฌ๊ธฐ์ ์ํ๋ฒณ์ด ์ ๋ง ํฌ๋ค๋ ๊ฒ์ ๋๋ค. ๊ต๊ณผ์๋ ์ผ๋ฐ์ ์ผ๋ก DFA/NFA/์ ๊ท ํํ์์ ๋ํด ์ด์ผ๊ธฐํ ๋ ํฌ๊ธฐ๊ฐ 1-5์ธ ์ํ๋ฒณ์ผ๋ก ์ ํ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ JS ์ ๊ท ํํ์์ ์ฌ์ฉํ๋ฉด ๋ชจ๋ ์ ๋์ฝ๋๊ฐ ์ํ๋ฒณ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค. ๋ฌผ๋ก , ํ๋ฑ/๋ถ๋ถ์งํฉ ํ ์คํธ๋ฅผ ์ํด ํฌ์ ๋ฐฐ์ด ๋ฐ ๊ธฐํ ์๋ฆฌํ ํดํน ๋ฐ ์ต์ ํ๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ ํจ์๋ฅผ ํํํ๋ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ด ์์ ์ ์์ต๋๋ค...
์ ๊ท ๋ ์ ๊ท ํ ๋น์ ๋ํ ์ ํ ๊ฒ์ฌ๋ฅผ ๋ค์ ํจ์จ์ ์ผ๋ก ์ํํ ์ ์๋ค๊ณ ํ์ ํฉ๋๋ค.
๊ทธ๋ฐ ๋ค์ ๋ชจ๋ ๋น์ ๊ท ํ ๋น์๋ ๋ช ์์ ํ์ ์ด์ค์ ๋ง ํ์ํ ์ ์์ต๋๋ค.
๋๋ ์ต๊ทผ์ ์์ ์ ํ ์๋ ์ฅ์น ํ๋ก์ ํธ์์ ์ผํ๊ธฐ ๋๋ฌธ์ ์ ๋ณด๊ฐ ์ฌ์ ํ ๋ด ๋ง์์ ์ ์ ํฉ๋๋ค =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 ์ญ์ฐธ์กฐ๋ ์ ์ผํ๊ฒ ์ํฉ์ ๋ง๋ ํ๋ก๋์ (๊ทธ๋ฆฌ๊ณ ์๋นํ ๊ฐ๋จํ๊ณ ์ ํ๋ ๊ฒ - ์ต๋ 9๊ฐ์ ๊ทธ๋ฃน๋ง ์ด์ ๊ฐ์ด ์ฐธ์กฐํ ์ ์์)์ด๋ฉฐ ๋๋จธ์ง ์ ๊ท ํํ์ ๋ฌธ๋ฒ์ ๊ท์น์ ์ด๋ฏ๋ก ์์ฌ๋ฉ๋๋ค. ๊ฒฐ์ ๊ฐ๋ฅํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ด ์ด๋ค ์๋ฏธ์์๋ ์ค์ฉ์ ์ด์ง ์๋ค๋ ๋ฐ ๋์ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๐
ํธ์ง: ์ ํ๋
@rozzzly์ ์ด ๋๊ธ ์ ์ผ๊ฐ์ TS 4.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์ ์ด ๋๊ธ ์ ์ผ๊ฐ์ TS 4.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
_์ ๋ฐ์ดํธ_: ์ด ๊ธฐ๋ฅ์ ์กฐ๊ธ ์ฌ์ฉํด ๋ณธ ํ์๋ ๋ง์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋ค๋ฃจ์ง ์์ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด, 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๊ฐ ๋ค์์ ์์๋ผ ํ์๊ฐ ์๋ ์ํฉ์์๋ ๋์ฑ ๊ทธ๋ ์ต๋๋ค. MyUnionExtended์ด๊ตญ์
์ธ์ ๊ฐ๋ ๋ ์์ฐ์ ์ธ ๊ธฐ์ฌ๋ฅผ ํ ์ ์์ ๋งํผ ์ง์์ ๊ฐ์ถ๊ฒ ๋ ๊ฒ์ ๋๋ค./
@rozzzly์ ์ด ๋๊ธ ์ ์ผ๊ฐ์ TS 4.1.0์์ ์๋ํจ์ ํ์ธํ์ต๋๋ค!
์ฐ์. ๋๋ ์์งํ ์ด๊ฒ์ด ๊ตฌํ๋๋ ๊ฒ์ ๊ธฐ๋ํ์ง ์์์ต๋๋ค. ์ ์ด๋ ์กฐ๋ง๊ฐ์ ์๋๋๋ค.
@chadlavi-casebook
๋ฆด๋ฆฌ์ค ์ ๋ณด์ ์ด ์ ํ ์ฌํญ์ ๋ํ ์ธ๊ธ์ด ์์์ต๋๋ค. ๊ฐ๋ฅํ ๋ชจ๋ ์ ํจํ ์กฐํฉ์ ๋ชฉ๋ก์ ์์ฑํฉ๋๋ค. ์ด ๊ฒฝ์ฐ 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์์ ์ผ๋ฐ ์ธ์ด๋ฅผ ๊ตฌํํ์ต๋๋ค.
๋ ์ ํํ๊ฒ๋ TS 4.1์ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ๊ฒฐ์ ๋ก ์ ์ ํ ์คํ ๋งํค์ ๊ตฌํํ์ต๋๋ค.
๋ด ๋ง์, ์ฐ๋ฆฌ๋ ์ด๋ฏธ TS์์ ํ๋ง ๊ธฐ๊ณ๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ DFA์ PDA๋ ๊ทธ์ ๋นํด "์ฝ์ต๋๋ค".
๊ทธ๋ฆฌ๊ณ ํ ํ๋ฆฟ ๋ฌธ์์ด์ ์ด๊ฒ์ ๋ ์ ์ฉํ๊ฒ ๋ง๋ญ๋๋ค.
ํต์ฌ ์ ํ์ ์ค์ ๋ก ๊ฐ๋จํ๊ณ < 30 LOC์ ์ ํฉํฉ๋๋ค.
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>;
์ด๋ ค์ด ๋ถ๋ถ์ธ ์๋ ์ฅ์น๋ฅผ ์ง์ ํ๋ ๊ฒ์ ๋๋ค.
ํ์ง๋ง ๋๊ตฐ๊ฐ TypeScript DFAโข ์์ฑ๊ธฐ์ ๋ํ ์ ๊ท์์ ๋ง๋ค ์ ์๋ค๊ณ ํ์ ํฉ๋๋ค...
๋ํ "๊ธธ์ด 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/CyberZHG/toolbox
์์ง๋ ฅ์ด ๋ ์์๋ค๋ฉด ์์ ๊ฐ์ ๊ฒ์ ๊ฐ์ ธ์ ์ ๊ท์์ TS DFAsโข๋ก ๋ฐ๊พธ๋ ๋ฐ ์ฌ์ฉํ ๊ฒ์ ๋๋ค. lol
์ข์์, ๋ฐฉ๊ธ ํ๋กํ ํ์ ์ ๋ง๋ค์์ต๋๋ค.
https://glitch.com/~sassy-valiant-heath
[ํธ์ง] https://glitch.com/~efficacious-valley-repair <-- ์ด๊ฒ์ ๋ ๋ณต์กํ ์ ๊ท์์ ๋ํด ๋ ๋์ ์ถ๋ ฅ์ ์์ฑํฉ๋๋ค.
[ํธ์ง] Glitch๋ ๋๋ฌด ์ค๋ซ๋์ ๋นํ์ฑ ์ํ์ธ ๋ฌด๋ฃ ํ๋ก์ ํธ๋ฅผ ๋ณด๊ดํ ๊ฒ ๊ฐ์ต๋๋ค. ์ฌ๊ธฐ ํ์ผ์ด ์๋ git repo๊ฐ โโ์์ต๋๋ค.
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 ์์, ์ด๋ฉ์ผ, ์ ํ ๋ฒํธ, ZipCode, swagger ํ์ฅ ๋ฑ๊ณผ ๊ฐ์ ๋จ์ํ ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ ์กฐํฉ์ผ๋ก ์ด๊ฑฐํ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก json ์คํค๋ง ์ฌ์๋ JSON ๊ฐ์ฒด์ ์คํค๋ง๋ฅผ ์ค๋ช ํ๋ ๋ฐ ์ฌ์ฉ๋๋ ํจํด ๋ฐ patternProperties ๋ TS ์ ํ ์์คํ ์ธก๋ฉด์์
regex-validated string type
๋ฐregex-validated string type of index
๋ผ๊ณ ํ ์ ์์ต๋๋ค.๋ชฉํ
๊ฐ๋ฐ์๊ฐ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ JSON ์คํค๋ง์ ํ ๊ฑธ์ ๋ ๊ฐ๊น์ด ์ ํ ์์คํ ์ ์ ๊ณตํ๊ณ ํ์ํ ๋ ๋ฌธ์์ด ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์์ด๋ฒ๋ฆฌ์ง ์๋๋ก ํฉ๋๋ค.
๊ตฌ๋ฌธ ๊ฐ์
์ด ๊ธฐ๋ฅ์ ๊ตฌํ์ 4๊ฐ์ง ๋ถ๋ถ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
์ ๊ท์ ๊ฒ์ฆ ์ ํ
์ ๊ท์ ๊ฒ์ฆ ๋ณ์ ์ ํ
๋์ผํ์ง๋ง ๋ ์ฝ๊ธฐ ์ฝ์ต๋๋ค.
์ธ๋ฑ์ค์ ์ ๊ท์ ๊ฒ์ฆ ๋ณ์ ์ ํ
๋์ผํ์ง๋ง ๋ ์ฝ๊ธฐ ์ฝ์ต๋๋ค.
๊ฐ๋ณํ ํ์ ๊ฐ๋
๊ทธ๋ฆฌ๊ณ ๊ฐ์
๋ ๋์ ๊ฐ๋ ์ฑ์ ์ํด ์ ์๋ ์ ํ ์ฌ์ฉ
๊ฐ์
์ธ๋ฑ์ค ์ ํ์ ๋ํ ์ ํ ๊ฐ๋
๊ฐ์
๋ ๋์ ๊ฐ๋ ์ฑ์ ์ํด ์ ์๋ ์ ํ ์ฌ์ฉ
๊ฐ์
์๋งจํฑ ๊ฐ์
๊ณผ์
๋ถํํ๋ ์ฐ๋ฆฌ๋ ์ด ๋ฌธ์ ๋ก ์ธํด ์ฌ๊ฐํ ์ฑ๋ฅ ์ํฅ ์์ด ํ ์ ๊ท์์ด ๋ค๋ฅธ ์ ๊ท์์ ํ์ ์ ํ์ธ์ง ํ์ธํ ์ ์์ต๋๋ค. ๊ทธ๋์ ์ ํํด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ค์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
๋ถํํ๋
string
๋ณ์๋ฅผregex-validated
๋ณ์์ ํ ๋นํ๋ ๊ฒ๋ ์ ํ๋์ด์ผ ํฉ๋๋ค. ์ปดํ์ผ ์๊ฐ์ ์ ๊ท์๊ณผ ์ผ์นํ๋ค๋ ๋ณด์ฅ์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค.๊ทธ๋ฌ๋ ์ฌ๊ธฐ์ ํ์๋ ๋๋ก ๋ช ์์ ์บ์คํธ ๋๋ ์ ํ ๊ฐ๋๋ฅผ ์ฌ์ฉํ ์
์ด ์ข๊ฒ๋ ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ ๊ฒฝ์ฐ๋ ์๋๋๋ค. ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ ์ฌ์ฉํ๋ ๋์ ํด๋น ๊ฐ์ด ์ ๊ท์๊ณผ ์ผ์นํ๋์ง ํ์ธํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ธ๋ฑ์ค์ ์ ํ ์ถ์
regex-validated type
์ธ๋ฑ์ค์ ๊ฐ๋จํ ๊ฒฝ์ฐ๋ ์ธ๋ฑ์ค ์ ํ์ ๋ํ ์ ํ ๋ณดํธ๋ฅผ ์ฐธ์กฐํ์ญ์์ค.๊ทธ๋ฌ๋ ๋ ๋ณต์กํ ๊ฒฝ์ฐ๊ฐ ์์ ์ ์์ต๋๋ค.
๋ฆฌํฐ๋ด์๋ ๊ทธ๋ฐ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๋ณ์์ ๊ฒฝ์ฐ ๊ฐ์ฅ ์ข์ ์ต์ ์ ๋ค์๋ณด๋ค ํ์ค์ ์ธ ์์์์ ๊ฐ์ด ์ ํ ๊ฐ๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค.
๊ทธ๋ฌ๋
Gmail
์ ํ์ ๋ํด ๋ ๋์ ์ ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค๋ฅธ ์ ํ์ด ์ถ์๋ฉ๋๋ค.์กฐํฉ ๋ฐ ๊ต์ฐจ๋ก
์ค์ ๋ก ์ผ๋ฐ์ ์ธ ์ ํ๊ณผ
regex-validated
์ ํ์ ์ค์ ๋ก ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ํฉ์งํฉ๊ณผ ๊ต์ฐจ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋ ๊ท์น์ด ํ์ํฉ๋๋ค.์ ๋ค๋ฆญ
์ ๋ค๋ฆญ์๋ ํน๋ณํ ๊ฒฝ์ฐ๊ฐ ์์ผ๋ฏ๋ก
regex-validated
type์ ์ผ๋ฐ ํ์ ๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ ๋ค๋ฆญ๊ณผ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค.์๋์ ๊ฐ์ ์ ์ฝ ์กฐ๊ฑด์ด ์๋ ์ ๋ค๋ฆญ์ ๊ฒฝ์ฐ
regex-validated
์ ํ์ ๋ฌธ์์ด์ฒ๋ผ ์๋ํฉ๋๋ค.๊ฐ์ ๋ฐฉ์ถ
์ผ๋ฐ์ ์ธ ์ ํ๊ณผ ๋ฌ๋ฆฌ
regex-validated
๋ ๋ฐฉ์ถ์ ์ฝ๊ฐ์ ์ํฅ์ ๋ฏธ์นฉ๋๋ค.๋ค์์ผ๋ก ์ปดํ์ผ๋ฉ๋๋ค.
ํธํ์ฑ ๊ฐ์
์ด ๊ธฐ๋ฅ์ ํธํ์ฑ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ์๋ํ๋ฉด ๊ทธ๊ฒ์ ๊นจ๋จ๋ฆด ์ ์๋ ๊ฒฝ์ฐ๋ง ์๊ณ
regex-validated
์ ํ์ด ์ผ๋ฐ ์ ํ๊ณผ ๋ฌ๋ฆฌ ์ํฅ์ ๋ฐฉ์ถํ๊ธฐ ๋๋ฌธ์ด๋ฏ๋ก ์ ํจํ TS ์ฝ๋์ ๋๋ค.์๋ ์ฝ๋๊ฐ ์๋ ๊ฒฝ์ฐ:
๊ทธ๋ฌ๋ ๋ ๋ฒ์งธ๋ ์ด๋ฏธ ์ ํจํ์ง ์์ง๋ง ๋ค๋ฅธ ์ด์ ๋ก ์ธํด(์ ํ ์ ์ธ์ด ์๋ชป๋์์ต๋๋ค).
๋ฐ๋ผ์ ์ด์ ์ด ์ ํ์ด
regex-validated
๊ฒฝ์ฐ๋ฅผ ๋๋นํ์ฌ ์ ํ๊ณผ ๋์ผํ ์ด๋ฆ์ ๊ฐ์ง ๋ณ์ ์ ์ธ์ ์ ํํด์ผ ํฉ๋๋ค.์ถ์
์ ๊ฐ ๋์ณค์ ์๋ ์๋ ๋ถ๋ถ์ ์์ ๋กญ๊ฒ ์ง์ ํด ์ฃผ์ธ์. ์ด ์ ์์ด ๋ง์์ ๋ค๋ฉด ์ด๋ฅผ ๋ค๋ฃจ๋ ํ ์คํธ๋ฅผ ๋ง๋ค๊ณ PR๋ก ์ถ๊ฐํ ์ ์์ต๋๋ค.