ì¬ì©íŽ 볎Ʞ: npm install yortus-typescript-typeof
ì°šìŽì 볎Ʞ: ì¬êž° .
TypeScriptì ì í ì¶ë¡ ì ëë¶ë¶ì 겜ì°ë¥Œ ì ë€ë£šê³ ììµëë€. ê·žë¬ë 컎íìŒë¬ìì ì ì¶í ì ìììë ë¶êµ¬íê³ ìµëª íìì ì°žì¡°íë íì€í ë°©ë²ìŽ ìë ëª ê°ì§ ìí©ìŽ ëšì ììµëë€. ëª ê°ì§ ì:
// Mapping to a complex anonymous type. How to reference the element type?
var data = [1, 2, 3].map(v => ({ raw: v, square: v * v }));
function checkItem(item: typeof data[0] /* ERROR */) {...}
// A statically-typed dictionary. How to reference a property type?
var things = { 'thing-1': 'baz', 'thing-2': 42, ... };
type Thing2Type = typeof things['thing-2']; // ERROR
// A strongly-typed collection with special indexer syntax. How to reference the element type?
var nodes = document.getElementsByTagName('li');
type ItemType = typeof nodes.item(0); // ERROR
// A factory function that returns an instance of a local class
function myAPIFactory($http: HttpSvc, id: number) {
class MyAPI {
constructor(http) {...}
foo() {...}
bar() {...}
static id = id;
}
return new MyAPI($http);
}
function augmentAPI(api: MyAPI /* ERROR */) {...}
// Declare an interface DRY-ly and without introducing extra type names
interface MyInterface {
prop1: {
big: {
complex: {
anonymous: { type: {} }
}
}
},
// prop2 shares some structure with prop1
prop2: typeof MyInterface.prop1.big.complex; // ERROR
}
í ê°ì§ ìë ìµëª
ì íì 맀ê°ë³ìë¡ ì¬ì©íë íšì륌 ì ìžíë ê²ì
ëë€. 맀ê°ë³ìì ì í 죌ììì ìŽë»ê²ë ì íì ì°žì¡°íŽìŒ í©ëë€. ê·žë ì§ ììŒë©Ž 맀ê°ë³ì륌 any
ë¡ ì
ë ¥íŽìŒ í©ëë€.
ííìì íê° íì§ ìê³ ìíë ì íì ì ì¶íë ìŽëì ëŒìŽì 륌 ì¬ì©íì¬ ë믞 ë³ì륌 ì ìží©ëë€(ìŽë ë°íì ë¶ìì©ì ìíì§ ìê³ ì í ì ì¶ë§ íêž° ë묞ì ì€ìí©ëë€). ì륌 ë€ìŽ:
let dummyReturnVal = null && someFunction(0, ''); // NB: someFunction is never called!
let ReturnType = typeof dummyReturnVal; // Now we have a reference to the return type
ìŽ íŽê²° ë°©ë²ìë ëª ê°ì§ ëšì ìŽ ììµëë€.
dummyReturnValue
곌 ê°ì ë³ì륌 ëì
íŽìŒ íš)_(죌ì: ìŽ ì룚ì ì #4233ìì ìŽë¯ž ì ìëìì§ë§ íŽë¹ 묞ì ìë 'ì ì íì'ëŒë íê·žê° ì§ì ëìŽ ììŒë©° ë€ë¥ž ëª ê°ì§ ë°ì íê² êŽë šë 묞ì ê° ììŒë¯ë¡ ìŽ ë³ëì 묞ì ì ëë€.)_
typeof
ì íŒì°ì°ìê° ììì ííììŽ ëëë¡ íì©í©ëë€. ìŽê²ì if (typeof foo() === 'string')
ì ê°ì ê° ìì¹ì typeof expr
ì ëíŽ ìŽë¯ž íì©ë©ëë€. ê·žë¬ë ìŽ ì ìì typeof
ê° type ElemType = typeof list[0]
ì ê°ìŽ ì í ì¿ŒëŠ¬ë¡ ì í ìì¹ìì ì¬ì©ë ë ììì ííìë íì©í©ëë€.
ìŽ ì ìì ìŽë¯ž ì¬ìì íì¬ ë¬žêµ¬ì ë°ì íê² ìŒì¹í©ëë€.
íì 쿌늬ë ê°ì²Ž 늬í°ëŽ, íšì ì ìž ë° ë€ìì€íìŽì€ ì ìžê³Œ ê°ì ë€ìí 구ì±ì ìíŽ ìì±ëë ìµëª íìì 캡ì²íë ë° ì ì©í©ëë€.
ë°ëŒì ìŽ ì ìì ìì ìì ê°ìŽ íì¬ ì ê³µëì§ ìë ìí©ì ê·ž ì ì©ì±ì íì¥íë ê²ì ëë€.
ì믞 첎ê³ë ìŽë¯ž ì¬ì 4.18.6 ì ëª ìë ê²ê³Œ ëìŒí©ëë€.
'typeof' ì°ì°ìë 몚ë ì íì íŒì°ì°ì륌 ì¬ì©íì¬ String Ʞ볞 ì íì ê°ì ìì±í©ëë€. ì íìŽ ììëë ìì¹ìì ì í 쿌늬(ì¹ì 3.8.10)ìì 'typeof'륌 ì¬ì©íì¬ ííì ì íì ìì±í ìë ììµëë€.
ì ìë ì°šìŽì ì ìë ìžì©ë ì¹ì 3.8.10 곌 êŽë šìŽ ììŒë©°, ì¬êž°ì ì·šìì í ì€ížë ì ê±°ëê³ êµµì í ì€ížë ì¶ê°ë©ëë€.
ì í 쿌늬ë typeof í€ìë
ì ííììŒë¡ 구ì±ë©ëë€.ííìì ìë³ì ííì(ì¹ì 4.3) ëë ìì± ì¡ìžì€ ííì(ì¹ì 4.13)ìŒë¡ ì²ëŠ¬ëë©°, ìŽííì ì íì¥ë ì í(ì¹ì 3.12)ìŽ ê²°ê³Œê° ë©ëë€. ë€ë¥ž ì ì ì í ì§ì 구묞곌 ì ì¬íê² ì í 쿌늬ë ìì±ë JavaScript ìœëìì ì§ìì§ê³ ë°íì ì€ë²í€ëê° ì¶ê°ëì§ ììµëë€.
ê°ì¡°íŽìŒ í ì (ì€íìë ìë€ê³ ìê°íì§ë§ ì°Ÿì ì ìì)ì ì í ì¿ŒëŠ¬ê° íŒì°ì°ì륌 íê° íì§ ìëë€ë ê² ì ëë€. ê·žê²ì íì¬ ì¬ì€ìŽë©° ë ë³µì¡í ííìì ëíŽìë ë§ì°¬ê°ì§ì ëë€.
ìŽ ì ìì ìë¡ìŽ 구묞ì ëì
íì§ ìê³ ì¿ŒëŠ¬í ì ìë ííì ì íìì typeof
륌 ë ì íì ìŒë¡ ë§ëëë€.
// Mapping to a complex anonymous type. How to reference the element type?
var data = [1, 2, 3].map(v => ({ raw: v, square: v * v }));
function checkItem(item: typeof data[0]) {...} // OK: item type is {raw:number, square:number}
// A statically-typed dictionary. How to reference a property type?
var things = { 'thing-1': 'baz', 'thing-2': 42, ... };
type Thing2Type = typeof things['thing-2']; // OK: Thing2Type is number
// A strongly-typed collection with special indexer syntax. How to reference the element type?
var nodes = document.getElementsByTagName('li');
type ItemType = typeof nodes.item(0); // OK: ItemType is HTMLLIElement
// A factory function that returns an instance of a local class
function myAPIFactory($http: HttpSvc, id: number) {
class MyAPI {
constructor(http) {...}
foo() {...}
bar() {...}
static id = id;
}
return new MyAPI($http);
}
type MyAPI = typeof myAPIFactory(null, 0); // OK: MyAPI is myAPIFactory's return type
function augmentAPI(api: MyAPI) {...} // OK
// Declare an interface DRY-ly and without introducing extra type names
interface MyInterface {
prop1: {
big: {
complex: {
anonymous: { type: {} }
}
}
},
// prop2 shares some structure with prop1
prop2: typeof (<MyInterface>null).prop1.big.complex; // OK: prop2 type is {anonymous: {type: {}}}
}
ë°ë : ë¹ìœí 구묞 믞í. ê°ë³ ì¬ë¡ë¥Œ ë€ë£šë ë첎 구묞ì #6179, #6239, #4555 ë° #4640ìì ì ìëììµëë€.
For : ë€ë¥ž 구묞ì í¹ì 겜ì°ì ë ì¢ì ë³ŽìŒ ì ìì§ë§ 몚ë ìë¡ ë€ë¥Žë©° ê°ê°ì íëì í¹ì 묞ì ë§ íŽê²°í©ëë€. ìŽ ì ìì ìŽë¬í 몚ë 묞ì ìì ì êž°ë 묞ì 륌 íŽê²°íë©° ê°ë°ìë ìë¡ìŽ 구묞ì ë°°ìž íìê° ììµëë€.
ë°ë : ì í ìì¹ì ííììŽ íŒëë©ëë€.
For : TypeScriptë ìŽë¯ž ë ê°ì§ ìë¯žë¡ typeof
륌 ì€ë²ë¡ëí©ëë€. ì í ì¿ŒëŠ¬ë¡ ìŽë¯ž ì í ìì¹ì ííìì ìëœíê³ íê°íì§ ìê³ íŽë¹ ì íì ê°ì žìµëë€. ìŽê²ì ìŽ ë¬žì ìì ì êž°ë 묞ì 륌 íŽê²°í ì ìëë¡ íŽë¹ ííììŽ ë¬Žììžì§ì ëí ì ìœì ìíí©ëë€.
ë°ë : ìŽê²ì êžžê³ ì¬ë¬ ì€ ì í 쿌늬륌 ìì±íë ë° ëšì©ë ì ììµëë€.
For : ì í 쿌늬ìì ê·žë ê² í ìŽì ë ìì§ë§ ë ë³µì¡í ííìì íì©íë ë°ìë 충ë¶í ìŽì ê° ììµëë€. ìŽê²ì Ʞ볞ì ìŒë¡ Martin Fowlerì ìž ììŽëž vs ëë í ì ëë€.
ìŽê²ì ìì í ìŽì ë²ì 곌 ížíëë ë³ê²œ ì¬íì
ëë€. êž°ì¡Žì 몚ë ìœëë ìí¥ì ë°ì§ ììµëë€. typeof
ì ì¶ê° êž°ë¥ì ì¬ì©íë ê²ì ìµížìžì
ëë€.
diff륌 볎멎 ì죌 ìì ë³í륌 볌 ì ììµëë€. 컎íìŒë¬ë 쿌늬ëë ì íì ìŽë¯ž ìê³ ììŒë¯ë¡ ê°ë°ììê² íìë ë¿ì ëë€. 묎ìí ì ìë ì±ë¥ ìí¥ì ììíì§ë§ ìŽê²ì í ì€ížíë ë°©ë²ì ëªšë¥Žê² ìµëë€.
ìŽ ì ììŽ ìžìŽ ìë¹ì€ë¡ 구íë TypeScript ë²ì ì ì¬ì©íëë¡ VS Code륌 ì€ì íìŒë©° 몚ë 구묞 ê°ì¡° íìì ìží 늬ìŒì€ë í ì€íží í ì벜í©ëë€.
.d.ts
íìŒìì ë³µì¡í ííììŽ ë°ìí ì ììµëë€.typeof
ì íŒì°ì°ìë IIFE륌 í¬íší 몚ë ííììŽê±°ë ë©ìë 볞묞ìŒë¡ ìì±ë íŽëì€ ííììŒ ì ììµëë€. ê·žë ê² í ìŽì ê° ìê°ëì§ ììµëë€. .d.ts
íìŒ( typeof
ì ì¬ì©í ì ììŒë©° ì£Œë³ ì»ší
ì€ížìì ì ì©í©ëë€). ë°ëŒì ìŽ ì ìì 결곌ë "묞ì¥ì ì£Œë³ ì»ší
ì€ížì ëíë ì ìì"ìŽ ë ìŽì ì격íê² ì¬ì€ìŽ ìëëŒë ê²ì
ëë€.
컎íìŒë¬ë ë€ì곌 ê°ì ìŒì ì²ëŠ¬íë ë° íìí 몚ë ë ŒëŠ¬ë¥Œ ìŽë¯ž ê°ì¶ê³ ìë ê² ê°ìµëë€.
function foo<X,Y>(x: X, y: Y) {
var result: typeof foo(x, y); // ERROR: 'result' is referenced in its own type annotation
return result;
}
몚ížíì§ ììµëë€. 쿌늬ì ííì곌 ìŒì¹íë ì€ë²ë¡ë륌 ì íí©ëë€.
declare function foo(a: boolean): string;
declare function foo(a: number): any[];
type P = typeof foo(0); // P is any[]
type Q = typeof foo(true); // Q is string
Intellisense ë±ì ì¬ì©íì¬ VS Codeìì ìŽê²ì ì¬ì©íë ë¹ ë¥ž ë°©ë²ì ìíë ì¬ëì ìíŽ ì¬êž°ì ëìŽí° repo ê° ììµëë€.
ì í P = foo(0) ì í; // Pë ìì[]
ì í Q = foo ì í(true); // Që 묞ììŽì ëë€.
ê° ëì ì íì ìžìë¡ ì¬ì©íë ê²ìŽ ë ì íší 구묞ìŽëŒê³ ìê°í©ëë€.
type P = typeof foo(number); // P is any[]
type Q = typeof foo(boolean); // Q is string
ê°ìŽ ìë ì íì ìžìë¡ ì ê³µíêž° ë묞ì íšìê° ížì¶ëì§ ìëë€ë ê²ìŽ ë ë¶ëª
í©ëë€. ë€ë¥ž ì ì ë 몚ížíë€ë ê²ì
ëë€. ìŽë€ ì¬ëë€ì typeof foo(false)
륌 ì¬ì©íê³ ìŽë€ ì¬ëë€ì typeof foo(true)
륌 ì¬ì©í©ëë€. ì íìŽ ìžìë¡ ìë ê²œì° ì¬ëë€ì typeof foo(boolean)
ë§ ìž ì ììµëë€.
@tinganho ì íí!
ì¬ì í #5185ë¡ typeof foo("abc")
륌 ìž ì ìì§ë§
ì¬êž°ì "abc"
ë ì±êží€ 묞ììŽ ì íì
ëë€.
@tinganho ëë ë¹ì ì ììŽëìŽì ëíŽ ìœê°ì ìê°ì íŽë³Žìê³ ìŽ ì ìì ëíŽ ëŽê° ì ížíë ê²ê³Œ ë¹ì ì ì ìì ëíŽ ì ížíë ë€ë¥ž ê²ì 볎ììµëë€. ê·íì ì ìì ê·íê° ì ê³µí ìŽì ë묞ì ì¢ìµëë€(ë ê°ëšíê³ ëª íí 구묞, ë 몚ížíê³ íšì ížì¶ì²ëŒ 볎ìŽì§ ìì). ëŽ ì ìì ëíŽ ì ížíë ì ì ìë¡ìŽ 구묞ì ëì íì§ ìì íì/ê²ì¬êž°ì ë³µì¡ì±ì ì¶ê°íì§ ììŒë©° ìžìì ëí ê°ëší ì í ìŽëŠìŽ ìë ë ë³µì¡í ìë늬ì€ë ì§ìíë€ë ê²ì ëë€.
foo(number)
구묞곌 ê°ì ê²ì ìì±íë ë§€ì° ê°ëší ë°©ë²ìŽ ìì§ë§ êž°ì¡Ž ííì 구묞 ë¶ì ë©ì»€ëìŠì ì¬ì©íë©Ž ìŽë»ê² ë ê¹ì? ê·žëì ì€íìŒë¡ _unary as_ëŒë ìë¡ìŽ ííì ëì
íìµëë€. as T
(null as T)
ìœìŽì
ëë€. ë¹ì ì Ʞ볞ì ìŒë¡ _'ëë ê°ì ëíŽ ì 겜 ì°ì§ ìì§ë§ ííììŽ X ì íì ê°êž°ë¥Œ ìí©ëë€'ëŒê³ ë§íê³ ììµëë€.
ìŽ ë³ê²œ ì¬í( Playground repo ìì 구ííš)ì ì¬ì©íë©Ž ì ìë 구묞ì íšì¬ ë ê°ê¹ìŽ ê²ì ìì±í ì ìì§ë§ ì¬ì í ìŒë° ííììŒë¡ 구묞 ë¶ìë©ëë€.
type P = typeof foo(as number); // P is any[]
type Q = typeof foo(as boolean); // Q is string
let prop2: typeof (as MyInterface).prop1.big.complex; // prop2 type is {anonymous: {type: {}}}
ìŽê²ì ëšì§ ë¹ ë¥ž ì€íìŽììµëë€. ëë±í 구묞ì ë€ì곌 ê°ì ì ììµëë€(íì§ë§ 구ííì§ë ìììµëë€).
type P = typeof foo(<number>); // P is any[]
type Q = typeof foo(<boolean>); // Q is string
let prop2: typeof (<MyInterface>).prop1.big.complex; // prop2 type is {anonymous: {type: {}}}
ë ë²ì§ž 구묞ì (<T> null)
ì ìœìŽìž <T>
ííìì ì¬ì©íì¬ _nullary ì í assertion_ìŽëŒê³ í ì ììµëë€.
@yortus , ì°ëŠ¬ë ì§ë 죌ì ìŽ ì ìì ëíŽ ìŽìŒêž°íë ë° ìê°ì 볎ëìµëë€. ë ìŒì° ê²ìíì§ ëª»íŽ ì£ì¡í©ëë€. í©ìë 1ìŽììµëë€. ìŒë¶ ì íì ì°žì¡°í ì ìë 묞ì ê° ììµëë€. ì륌 ë€ìŽ íšìì ë°í ëë íŽëì€ ííìì ìžì€íŽì€ ì íìŽ ììµëë€. 2. ì í ìì¹ì ííìì ì¶ê°íë ê²ì ì°ëŠ¬ê° íží ìŒìŽ ìëëë€.
@tinganho ì ì ìë ì°ëŠ¬ê° ìŽìŒêž°í ê² ì€ íëììµëë€. 구ííêž°ê° ë ë³µì¡í ì ìì§ë§ ë ë§ìì ê²ìŽëŒê³ ìê°í©ëë€. ìë¡ìŽ ëší ì°ì°ì륌 ì¶ê°íê±°ë ìºì€íž 구묞ì ì¬ì©íë ê²ì ì í ìŽëŠì ì¬ì©íë ê²ë§íŒ ì°ìíì§ ììµëë€.
ì€ë ì¬ë¡ê·žìì ꜀ ì€ë«ëì í ë¡ íìµëë€. ì¬êž°ìì "PR ìëœ"ì "구íìŽ ë묎 ë¯žì¹ ê²ìŒë¡ íëª ëì§ ìëë€ë ê°ì íì PR ìëœ"ì ëë€.
@tinganho ì ì ìì (ì ìŽë ë€ë¥ž ìµì ì ë¹íŽ) ꜀ ì¢ì 볎ìŽë©° ìŽê²ì 구ííë ì ì ì PRì ë³Žê³ ì¶ìµëë€.
ê¹ë€ë¡ìŽ ì ì f(number)
ë f(0)
ì ë°í ì íì íŽê²°íêž° ìíŽ ìì í ë³ëì ìœë 겜ë¡ë¥Œ ê°ê³ ì¶ì§ ìë€ë ê²ì
ëë€. ê·žë¬ë 곌ë¶í íŽê²° ìê³ ëŠ¬ìŠì _types_ ìžížê° ìë _expressions_ ìžížë¡ ìì
íê³ ììµëë€. ê·žë¬ë ì°ëŠ¬ë ìœê°ì ìììë¡ ìŽê²ìŽ ê°ëšíŽìŒ íë€ê³ ìê°í©ëë€.
Ʞ볞 공격 ê³íì ë€ì곌 ê°ìµëë€.
typeof
구묞 ë¶ì ì 묞ë²ì íì¥íì¬ íšì ížì¶, ìì± ì¡ìžì€ ë° ìžë±ì±ë ìì± ì¡ìžì€ì ê°ì ê²ì íì©í©ëë€.parseType
íšì륌 ì¬ì©í©ëë€. ìŽê²ì TypeNode
륌 ìì±íì§ë§, ì í 쿌늬ì 컚í
ì€ížìì 구묞 ë¶ìë ì íìì ëíëŽë íë귞륌 ë
žëì ì€ì í©ëë€.checkExpression
ë ìŽ íë귞륌 íìžíê³ ìŒë° ííì ì²ëŠ¬ ëì getTypeFromTypeNode
륌 ížì¶í©ëë€.@mhegazy , @RyanCavanaugh íìŽ ìŒë§ë ë§ì ìœë ìŒìŽì€ë¥Œ ë
Œìíëì§ ì ëªšë¥Žê² ëë°, ì€ëª
ì ìíŽ ì¬êž°ì ëª ê°ì§ë¥Œ ê°ì žìë ë ê¹ì? ìëì ì¬ë¬ ìì 륌 ëìŽíê³ typeof
ìì
ì 결곌ëŒê³ ìê°íë ê²ìŒë¡ ê° ìì ì 죌ìì ë¬ììŒë©° ìì¬ì€ë¬ìŽ 겜ì°ìë 묌ìí륌 íìíìµëë€.
var data = [1, 2, 3];
const LOBOUND = 0;
type Elem1 = typeof data[0]; // number
type Elem2 = typeof data[999999]; // number or ERROR?
type Elem3 = typeof data[1+2]; // ERROR or number?
type Elem4 = typeof data[LOBOUND]; // ERROR or number?
var tuple: [number, string] = [123, 'abc'];
type Elem4 = typeof tuple[0]; // number or number|string?
type Elem5 = typeof tuple[1]; // string or number|string?
type Elem6 = typeof tuple[999999]; // number|string or ERROR?
const ABC: 'a-b-c' = 'a-b-c';
let dict = { 'a-b-c': 123, 'd-e-f': true };
type Prop1 = typeof dict['a-b-c']; // number
type Prop2 = typeof dict['d-e-f']; // boolean
type Prop3 = typeof dict[ABC]; // ERROR or number or any?
// A simple function
declare function f1(n: number): string[];
type Ret1 = typeof f1(number); // string[]
type Ret2 = typeof f1(0); // ERROR or string[]?
// An asynchronous function that either accepts a callback or returns a Promise
declare function f2(n: number): Promise<string[]>;
declare function f2(n: number, cb: (err?: any, result?: string[]) => void): void;
type Ret3 = typeof f2(number); // Promise<string[]>
type Ret4 = typeof f2(number, any); // void
type Ret5 = typeof f2(number, Function); // ERROR: Function not assignable to callback
type Ret6 = typeof f2(number, (err: any, result: string[]) => void); // void
type Ret7 = typeof f2(number, (...args) => any); // void
// A special function-like object
interface Receiver {
(data: string[]): void;
transmogrify(): number[];
}
declare function f3(n: number, receiver: Receiver): Promise<void>;
declare function f3(n: number, callback: (err?: any, result?: string[]) => void): void;
type Ret8 = typeof f3(number, Receiver); // Promise<void>
type Ret9 = typeof f3(number, any); // ambiguous? or picks first overload?
type Ret10 = typeof f3(number, Function); // ERROR
type Ret11 = typeof f3(number, (...args) => any); // void since not assignable to Receiver
// A function with parameter destructuring
interface CartesianCoordinate {/***/}
interface PolarCoordinate {/***/}
declare function f4({ x: number, y: number }): CartesianCoordinate;
declare function f4({ r: number, t: number }): PolarCoordinate;
type Ret12 = typeof f4(any); // ambiguous? or picks first overload?
type Ret13 = typeof f4({x;y}); // CartesianCoordinate
type Ret14 = typeof f4({r;t}); // PolarCoordinate
type Ret15 = typeof f4({x;r;t;y}); // ambiguous? or picks first overload?
// Type-ception: is there anything wrong with typeof-in-typeof?
declare function f5(n: number, receiver: Receiver): Promise<void>;
declare function f5(n: number, callback: (err?: any, result?: string[]) => void): void;
function myCallback(err, result) {/***/}
var myReceiver: Receiver;
type Ret16 = typeof f5(number, typeof myReceiver); // Promise<void>
type Ret17 = typeof f5(number, typeof myCallback); // void
ìŠ, ìì typeof (<MyInterface> null).prop1.big.complex;
ìì ì
ëë€.
ëë ìŽê²ìŽ ë²ì륌 ë²ìŽë ì§ìëì§ ìì ê²ìŽëŒë ìì ì견ìì ê°ì žìµëë€. ê·ž ë§ìµëê¹?
var data = [1, 2, 3];
const LOBOUND = 0;
type Elem1 = typeof data[0]; // number
type Elem2 = typeof data[999999]; // number
type Elem3 = typeof data[1+2]; // ERROR, only literals allowed here
type Elem4 = typeof data[LOBOUND]; // number when const resolution is done, otherwise any
var tuple: [number, string] = [123, 'abc'];
type Elem4 = typeof tuple[0]; // number
type Elem5 = typeof tuple[1]; // string
type Elem6 = typeof tuple[999999]; // number|string
const ABC: 'a-b-c' = 'a-b-c';
let dict = { 'a-b-c': 123, 'd-e-f': true };
type Prop1 = typeof dict['a-b-c']; // number
type Prop2 = typeof dict['d-e-f']; // boolean
type Prop3 = typeof dict[ABC]; // number when const resolution work is done, otherwise any
// A simple function
declare function f1(n: number): string[];
type Ret1 = typeof f1(number); // string[]
type Ret2 = typeof f1(0); // error, 0 is not a type
// An asynchronous function that either accepts a callback or returns a Promise
declare function f2(n: number): Promise<string[]>;
declare function f2(n: number, cb: (err?: any, result?: string[]) => void): void;
type Ret3 = typeof f2(number); // Promise<string[]>
type Ret4 = typeof f2(number, any); // void
type Ret5 = typeof f2(number, Function); // ERROR: Function not assignable to callback
type Ret6 = typeof f2(number, (err: any, result: string[]) => void); // void
type Ret7 = typeof f2(number, (...args) => any); // void
// A special function-like object
interface Receiver {
(data: string[]): void;
transmogrify(): number[];
}
declare function f3(n: number, receiver: Receiver): Promise<void>;
declare function f3(n: number, callback: (err?: any, result?: string[]) => void): void;
type Ret8 = typeof f3(number, Receiver); // Promise<void>
type Ret9 = typeof f3(number, any); // picks first overload
type Ret10 = typeof f3(number, Function); // ERROR
type Ret11 = typeof f3(number, (...args) => any); // void since not assignable to Receiver
// A function with parameter destructuring
interface CartesianCoordinate {/***/}
interface PolarCoordinate {/***/}
declare function f4({ x: number, y: number }): CartesianCoordinate;
declare function f4({ r: number, t: number }): PolarCoordinate;
type Ret12 = typeof f4(any); // picks first overload
type Ret13 = typeof f4({x;y}); // CartesianCoordinate
type Ret14 = typeof f4({r;t}); // PolarCoordinate
type Ret15 = typeof f4({x;r;t;y}); // picks first overload
// Type-ception: is there anything wrong with typeof-in-typeof?
declare function f5(n: number, receiver: Receiver): Promise<void>;
declare function f5(n: number, callback: (err?: any, result?: string[]) => void): void;
function myCallback(err, result) {/***/}
var myReceiver: Receiver;
type Ret16 = typeof f5(number, typeof myReceiver); // Promise<void>
type Ret17 = typeof f5(number, typeof myCallback); // void
ì¬êž°ì ë¬Žìš ìŒìŽ ìŒìŽëëì§ ê¶êží©ëë€.
const number = "number";
type Ret3 = typeof f2(number); // What happens here?
@SaschaNaz ì¢ì ì§ë¬žì ëë€. ë¹ì·í ìí©:
class MyClass { foo; bar; }
declare function f(inst: MyClass): number;
type Ret = typeof f(MyClass); // number (presumably)
ìŽ ê²œì° MyClass
_value_(ìŠ, ìì±ì íšì) ì ì MyClass
_type_ì ê³ ë €íë ê²ìŽ $# typeof f(MyClass)
ìì ìë¯žê° ììµëë€. ì ìë Ret = number
ë¡ ì°ê²°ëê³ íìë error: MyClass is not a type
ì ê°ì ê²°ê³Œë¡ ìŽìŽì§ëë€.
_type_곌 _const value_륌 몚ë ì°žì¡°íë ìŽëŠì ëìŒí ë
ŒëŠ¬ê° ì ì©ë©ëê¹? ê·íì ììì ìŽë number
ì íìŽ íì const ê° number
ë³Žë€ ì°ì íë€ë ê²ì ì믞í©ëë€. @RyanCavanaughì ëí ìê°ìŽ ììµëê¹?
ë§ìµëë€, ì°ëŠ¬ë ìŽê²ì íì
ííìì ìŒë°ì ìž ìë¯žë¡ íŽê²°í ê²ì
ëë€( ë§ì¹ var x: [whatever]
륌 ìì±í ê²ì²ëŒ). ë°ëŒì typeof f(MyClass)
ë ìžì€íŽì€ ìž¡ìì f
륌 ížì¶íë ê²ì ì°žì¡°íê³ typeof f(typeof MyClass)
ë ìì±ì íšìë¡ f
륌 ížì¶íë ê²ì ì°žì¡°í ì ììµëë€.
ê·žë ë€ë©Ž @SaschaNaz ì ìì ë number
륌 _const ê°_ìŽ ìë _type_ìŒë¡ ëª
ííê² ì°žì¡°íê³ ìì§ ììµëê¹?
const number = "number";
type Ret3 = typeof f2(number); // Promise<string[]>
@RyanCavanaugh ìž ë²ì§ž ì¬ì© ì¬ë¡ ê·žë£¹ìŽ ë²ì륌 ë²ìŽë¬ëì§ íìží ì ììµëê¹? ì륌 ë€ìŽ OPìì:
// Declare an interface DRY-ly and without introducing extra type names
interface MyInterface {
prop1: {
big: {
complex: {
anonymous: { type: {} }
}
}
},
// prop2 shares some structure with prop1
prop2: typeof (<MyInterface>null).prop1.big.complex; // OK: prop2 type is {anonymous: {type: {}}}
}
ìŽ ì¬ì© ì¬ë¡(구묞ì êŽê³ììŽ)ë íì¬ ì§ìëì§ ììµëë€. ë§ìµëê¹?
this
ííìì íì©íì¬ ìŽ ë¬žì 륌 ë€ë£šìŽìŒ íë€ê³ ìê°í©ëë€.
prop2: typeof this.prop1.big.complex;
const
묞ì ë ë€ë¥ž typeof
ì ìíŽ íŽê²°ëìŽìŒ íë€ê³ ìê°í©ëë€.
type Ret3 = typeof f2(typeof number); // typeof number is string so error here
... ìŽë ê² íë©Ž typeof data[LOBOUND]
ì°šëšë©ëë€.
@mhegazy typeof this
ì¢ì ììŽëìŽì
ëë€. ëë ìŽê²ìŽ ìŽ ì ìì ìíŽ ë§ë ë¶êž°ë 구íìì ìŽë¯ž ìëíë€ë ê²ì 깚ë¬ììµëë€. êžì, ê·žê²ì ìì
ì ìíŽ ìëí©ëë€. ìží°íìŽì€ì ê²œì° ì€ë¥ê° ìì§ë§ this
ì íì íì any
ë¡ ì ì¶ë©ëë€. ë¶êž°ë implì íì¬ ì¶ë ¥:
class MyClass {
prop1: {
big: {
complex: {
anonymous: { type: {} }
}
}
};
prop2: typeof this.prop1.big.complex; // prop2 type is {anonymous: {type: {}}}
}
interface MyInterface {
prop1: {
big: {
complex: {
anonymous: { type: {} }
}
}
};
prop2: typeof this.prop1.big.complex; // prop2 type is any
}
ìží°íìŽì€ ì ìž ëŽìì this
륌 ì¶ë¡ í ì ììµëê¹? ìëë©Ž ìŽ êž°ë¥ìŽ íŽëì€ë¡ ì íëìŽ ììµëê¹?
#6179ì Angularì ëíŽ ë ê°ì§ ìì ì ë§íê³ ì¶ìµëë€.
// A factory function that returns an instance of a local class
function myAPIFactory($http: HttpSvc, id: number) {
class MyAPI {
constructor(token: string) {...}
foo() {...}
bar() {...}
static id = id;
}
return MyAPI;
}
type MyAPIConstructor = typeof myAPIFactory(null, 0); // OK: MyAPI is myAPIFactory's return type
function augmentAPI(api: MyAPIConstructor) {...} // OK
맀ê°ë³ìì ìë íŽ ì ììµëë€. 15ê°ì 맀ê°ë³ì륌 ê°ì íŽ ë³Žê² ìµëë€. ëìì ì€ë²ë¡ëê° ììŒë©° typeof
ì 맀ê°ë³ìê° íìí ì€ë²ë¡ëë§ ììµëë€. ë°ëŒì ìŽ ê²œì° ë€ì곌 ê°ì 구묞ì ìê°í ì ììµëê¹?
type MyAPI = typeof myAPIFactory(...);
í©í 늬 íšìë ìŒë°ì ìŒë¡ ì첎 ì ì ë³ìì í ë¹ëì§ ììµëë€. íšì ííììŽ ì¬ì©ë©ëë€.
angular.module('app').factory('MyAPI', function($http: HttpSvc, id: number) { /*...*/ });
ê·žê² ë³Žíµì 몚ìµì
ëë€. ì¬êž°ì ì ì ìë¯ìŽ typeof
ë ì í ì¬ì©í ì ììµëë€.
@thron0 ëŽ ì§êŽì 맀ê°ë³ìê° ëª ê° ìŽì ìì§ë§ _ëí_ ìµëª ì íì ë°ííë ê²ì ë§€ì° ë묌ë€ë ê²ì ëë€. ìŽë»ê² ìê°íŽ?
Angular 1ìŽ ë ìŒì°ìŽ ìëëŒ í¬ê·íŽì§ë©Ž í¬ê·íŽì§ ê²ì ëë€.
Ʞ볞ì ìŒë¡ ì€ëª íì ëŽì©ì ìŒë°ì ìž Angular _factory_ê° ë¬Žììžì§ì ëë€.
맀ê°ë³ìê° ëª ê° ìŽì ìì§ë§ ìµëª ì íì ë°ííë ê²
ì¢ ìì±ì 맀ê°ë³ìë¡ ì¬ì©íê³ _service_ì ìžì€íŽì€ë¥Œ ìì±íë íšìì ëë€. ë§ì ìì 맀ê°ë³ìê° ë²ê±°ë¡ìž ì ìë€ê³ ìê°í ì ìì§ë§ 묞ì ë ìŽë¬í í©í ëŠ¬ê° ì§ì ížì¶ëì§ ìëë€ë ê²ì ëë€. DI 컚í ìŽëê° ìŽë¥Œ ížì¶í©ëë€. í©í 늬ë ìŽë€ ê²ìŽ ìì¡Žì±ìŒë¡ ë°í ê°(ìë¹ì€)ì ì구í ë ížì¶ë©ëë€. ê·žëŠ¬ê³ ìë¹ì€ë Angularìì íì ì±êží€ìŽë¯ë¡ í ë²ë§ ížì¶ë©ëë€. ê·žë¬ë ìë¹ì€ë 묎ììŽë ë ì ììŒë¯ë¡ ì±êží€ìŽ ìë ëììŽ íìí ê²œì° í©í 늬ë ìì±ì(ëë í©í 늬 íšì)륌 ë°íí ì ììµëë€. ìŽ ìœë ìì ììì²ëŒ:
angular.module('app').factory('MyAPI', function($http: HttpSvc, id: number) {
class MyAPI {
constructor(token: string) {...}
foo() {...}
bar() {...}
static id = id;
}
return MyAPI;
});
ìŽ ìí©ì ëí íì¬ íŽê²° ë°©ë²ì ë€ì곌 ê°ìµëë€.
class MyAPI {
// dependencies (1)
protected $http: HttpSvc;
protected id: number;
constructor(token: string) {...}
foo() {...}
bar() {...}
// Static properties cannot be used with this approach because:
// 1) this class is a global variable so it can be shared by different
// instances of the DI container,
// 2) the id property isn't available here as it's initialized in the subclass
//// static id0 = id;
}
angular.module('app').factory('MyAPI', function($http: HttpSvc, id: number) { // (2)
return class extends MyAPI {
$http = $http; // (3)
id = id;
};
});
// this type is needed for type annotations in the services that require MyAPI as a dependency
type MyAPIConstructor = typeof MyAPI;
angular.module('app').factory('someOtherService', function(MyAPI: MyAPIConstructor) {
var api = new MyAPI('qwerty');
/* ... */
});
볎ìë€ìíŒ ìì í ì¶íê³ ê³ íµ ì€ëœìµëë€. ì¢ ìì±ì ìž ë² ëìŽíŽìŒ í©ëë€. ë ë§ì ì¢ ìì±ìŽ ìë ê²œì° ìŒë°ì ìž ë°©ì(í©í 늬 íšì ëŽë¶)ìŒë¡ íŽëì€ë¥Œ ìì±íê³ íŽë¹ ìë¹ì륌 ìí ìží°íìŽì€ë¥Œ ì ìžíë ê²ìŽ ë ê°ëší©ëë€.
ìë íìžì, ì ë typeof 구묞/ìë¯žë¡ ì ê·žëë¡ ëê³ ëì ê°ëší ì í ì¡ìžì€ ëìíì 구ííë ê²ì ì ìíê³ ì¶ìµëë€.
ì í 구묞 íì¥ì ììíŽ ëŽ ìë€.
type ::= ... | literalType | type typeAccess | guarded
guarded ::= "type" id
literalType ::= stringLiteral | numberLiteral | symLiteral | booleanLiteral
typeAccess ::= typeField | typeSubscript | typeCall
typeField ::= "." id
typeSubscript ::= "[" type "]"
typeCall ::= "(" [type {"," type}] ")"
ë²ìì ê° ìë³ìë ë ìí°í°ì ëìì ë°ìžë©ë ì ììµëë€.
ì í ê°ëë ì ìë§ ì¶ì¶í©ëë€. ë°ëŒì
class A {}
var a: A;
ì ëë±íë€
class A {}
var a: type A;
ìŽ ê²œì° ìì ìŽ ìë€ë©Ž
class ABC {
a: number;
b(x: number): string;
c:string[];
d:[number, string];
}
ê·žë¬ë©Ž ì°ëŠ¬ë ìž ì ììµëë€
var a: (type ABC).a; // number
var b: (type ABC).b(number); // string
var c: (type ABC).c[number]; // string
var d: (type ABC).c[0]; // number
ëí ìŽí ë²ììì ëìŒí ìë³ì ìë _type_ ìí°í°ì _value_ ìí°í°ë¥Œ ë³í©íë ë°©ë²ì ë€ë£¹ëë€.
interface SAME {
x: number;
}
namespace SAME: {
export type x = boolean;
export var x: string;
}
var a: SAME.x // boolean
var b: (type SAME).x // number
var b: (typeof SAME).x // string
@RyanCavanaugh , @sandersn ìŽ ììŽëìŽë¥Œ ê²í í ì ììµëê¹?
ì ììì íí ì íì ìŽë»ê² í¬ì°©í©ëê¹?
2016ë 5ì 19ìŒ ëª©ììŒ 12:26 Anatoly Ressinì ì늌 @github.comìì ë€ì곌 ê°ìŽ ìŒìµëë€.
ìë íìžì, ì ë typeof 구묞/ìë¯žë¡ ì ê·žëë¡ ëë ê²ì ì ìíê³ ì¶ìµëë€.
ëì ê°ëší ì í ì¡ìžì€ ëì륌 구ííììì€.ì í 구묞 íì¥ì ììíŽ ëŽ ìë€.
ì í ::= ... | 늬í°ëŽ ì í | ì í ì¡ìžì€ | 겜ë¹
볎ížë ::= "ì í" ID
늬í°ëŽ ì í ::= 묞ììŽ ëŠ¬í°ëŽ | ì«ì늬í°ëŽ | ì¬ë³ŒëŠ 늬í°ëŽ | ë¶ìž 늬í°ëŽ
typeAccess ::= typeField | ì í첚ì | íì ìœ
typeField ::= "." ID
typeSubscript ::= "["ì í "]"
typeCall ::= "(" [ì í {"," ì í}] ")"ë²ìì ê° ìë³ìë ëìì ë ê°ì ìë³ìì ë°ìžë©ë ì ììµëë€.
ìí°í°:
- 컎íìŒ ìê° ì í
- ë°íì ê°
_type_ ê°ëë ì ìë§ ì¶ì¶í©ëë€. ë°ëŒì
íŽëì€ A {}
ììŽ: ììŽì ëë±íë€
íŽëì€ A {}
ììŽ: AíìŽ ê²œì° ìì ìŽ ìë€ë©Ž
íŽëì€ ABC {
a: ë²íž;
b(x: ì«ì): 묞ììŽ;
c:묞ììŽ[];
d:[ì«ì, 묞ììŽ];
}ê·žë¬ë©Ž ì°ëŠ¬ë ìž ì ììµëë€
var a: (ABC ì í).a; // numbervar b: (ABC ì í).b(ì«ì); // stringvar c: (ABC ì í).c[ì«ì]; // stringvar d: (ABC ì í).c[0]; // ì«ì
ëí _type_ ìí°í°ì _value_ ìí°í°ë¥Œ ë³í©íë ë°©ë²ë ë€ë£¹ëë€.
ìŽí ë²ììì ëìŒí ìë³ì.ìží°íìŽì€ ëìŒ {
x: ì«ì;
}ë€ìì€íìŽì€ ëìŒ: {
ëŽë³ŽëŽêž° ì í x = ë¶ìž;
ëŽë³ŽëŽêž° ë³ì x: 묞ììŽ;
}
var a: SAME.x // booleanvar b: (ì í SAME).x // numbervar b: (typeof SAME).x // 묞ììŽ@RyanCavanaugh https://github.com/RyanCavanaugh , @sandersn
https://github.com/sandersn ìŽ ììŽëìŽë¥Œ ê²í í ì ììµëê¹?â
ìŽ ì€ë ëì ê°ì íêž° ë묞ì ìŽ ë©ìì§ë¥Œ ë°ê³ ììµëë€.
ìŽ ìŽë©ìŒì ì§ì ëµì¥íê±°ë GitHubìì íìžíìžì.
https://github.com/Microsoft/TypeScript/issues/6606#issuecomment -220378019
ê·íì ìë typeof ì ìŒë¡ 구ë¶ë ííì곌 type ìì± ì í #1295ê° ë§€ì° ì ì¬í ì ììì ìêž°ìíµëë€. íëë ë ì ì ìŽì§ë§ ë€ë¥ž íëë ë ìëì ì ëë€.
typeof í€ìë륌 걎ëë°ë ììŽëìŽë ë§ìì ëëë€.
prop2: this.prop1.big.complex;
ê·íì ììì @mhegazy ë this-expression
typeof
륌 ì¬ì©íê³ ììµëë€.
prop2: typeof this.prop1.big.complex;
ì€ë ì°ëŠ¬ë ìŽê²ì í ì ìêž° ë묞ì:
someProp: this;
ëŽ ìê°ì ë ë§ì ì ìŒë¡ 구ë¶ë ìì±ì ëí ìì 구묞ì ìžìœíë©Ž ë€ì곌 ê°ìµëë€.
someProp: this.prop1.prop2.prop3;
ê·žëŠ¬ê³ ìëëë€:
someProp: typeof this.prop1.prop2.prop3;
ê·žëŠ¬ê³ ìžìœì ê³ìíë €ë©Ž typeof륌 íšê» 걎ëë°ì§ ìê² ìµëê¹?
someProps: foo(number)
typeof륌 íšê» 걎ë ë°ì§ ìë ìŽì ë 묎ìì ëê¹?
ëŽê° ìê°í ì ìë í ê°ì§ ìŽì ë íŽëì€ì ìžì€íŽì€ 쪜ì ì°žì¡°íëì§ ìëë©Ž ì ì 쪜ì ì°žì¡°íëì§ ëªšížíŽì§êž° ë묞ì ëë€.
class C {}
// Does 'x' have the instance type of 'C',
// or does it have the shape of its constructor?
let x: C;
ë€ë¥ž ìží°íìŽì€ ëŽìì ìží°íìŽì€ì ìì± ì íë ì°žì¡°íê³ ì¶ìµëë€. ëŽ ì륌 #10588ë¡ ê²ìíìŒë©° íì¬ ìŽ í°ìŒì ìíŽ íìëììµëë€.
ë€ì곌 ê°ìŽ ìì±íë ê²ìŽ ì¢ìµëë€.
interface Foo {
bar: string;
}
interface Box<T> {
container: T;
}
interface FooWithBoxedProps {
bar: Box<Foo.bar>; // OR: bar: Box<typeof Foo.bar>;
}
ìŽê²ì ë€ì곌 ê°ìŽ ë²ìë©ëë€.
interface Foo {
bar: string;
}
interface Box<T> {
container: T;
}
interface FooWithBoxedProps {
bar: Box<string>;
}
ìŽì ì ìžêží ìëëŠ¬ì€ ì€ ìŒë¶ë ìŽì _ììžíë ì¡ìžì€ ì í_ìŒë¡ ííí ì ììµëë€(#11929). ìŽ êž°ë¥ì íì€ typeof
ííì곌 ê²°í©íë©Ž ë€ì곌 ê°ì 결곌륌 ì»ì ì ììµëë€.
interface MyInterface {
prop1: {
big: {
complex: {
anonymous: { type: {} }
}
}
},
// prop2 shares some structure with prop1
prop2: MyInterface["prop1"]["big"]["complex"];
}
ê·žëŠ¬ê³ ê·žê²ì ìëí©ëë€! (íì¬ typescript@nextì ìì)
ëë ë€ì곌 ê°ì ìì°ì€ë¬ìŽ ê²ìŽ ë¹ì·í ê²ìŽëŒê³ ìê°íì§ë§ íšìì ê²œì° ë€ì곌 ê°ì "íšì ížì¶ ì í"ìŽ ììµëë€.
interface FunctionLike{
(arg1 : number, arg2 : string) : {a : number; b : string;}
}
type ReturnType = FunctionLike(number, string); // {a : number; b : string;}
typeof
ì°ì°ìì ìì°ì€ëœê² ê²°í©í ì ìëë¡
interface BigThing {
testString: string;
testNumber: number;
testBoolean: boolean;
}
function getSmallThing(thing:BigThing){
return {
testString : thing.testString,
testBoolean : thing.testBoolean
}
}
type SmallThing = typeof getSmallThing(BigThing) // {testString: string; testBoolean : boolean}
ê·žëŠ¬ê³ ìŽê²ì ìŽ ì€ë ë(@tinganho)ì ìì ë¶ë¶ìì ìŽë¯ž ì ìë êµ¬ë¬žìž ê² ê°ìµëë€. :)
íì§ë§ _ììžíë ì¡ìžì€ ì í_ìŽ ì§êž íë ê²ì²ëŒ íì¬ typeof
ì°ì°ìë¡ ë©ì§ê² 구ì±ëë ë ìŒë°ì ìž êž°ë¥ìŽ ë ê²ì
ëë€.
ê·žë¬ë ëª ê°ì§ ì§ë¬ž/ìì¬ìŽ ì¬ì í ëšì ììµëë€.
typeofreturn
ëë returnof
)êž°ì ì ìŒë¡ ê°ë¥í ê² ê°ìµëë€. ìžì륌 íìží íìê° ìëë¡ ì€ë²ë¡ë íìž/ì í ìžì ì ì¶ë¥Œ 늬í©í ë§íŽìŒ í ì ììµëë€. ì ë€ëŠìŽ ì¶ê° 묞ì 륌 ë묎 ë§ìŽ ì êž°íë€ê³ ìê°íì§ ììµëë€. í ê°ì§ ì§ë¬žì ížì¶ê³Œ ìŒì¹íë 곌ë¶íê° ììŒë©Ž ìŽë»ê² ëëì§ì ëë€.
ìŽ êž°ë¥ìŽ ë°ëì§íì§ ì¬ë¶ë ë¶ëª íì§ ìë€ê³ ìê°í©ëë€. íšìê° ë§€ì° ì êµí ìµëª ì íì ë°ííë ê²œì° ìŽë¬í ë°©ììŒë¡ ì°žì¡°í íìê° ìëë¡ ì íì ìŽëŠì ì§ì íë ê²ìŽ ìì±ììê² ë ëììŽ ëì§ ììê¹ì? ëë ìŽê²ìŽ ëšì§ 묞첎 ì ížëì 귌거í ê²ìì ìžì í©ëë€. ì€ì ìì ìŒë§ë ížëŠ¬íê² ì¬ì©í ì ììì§ ëªšë¥Žê² ìµëë€. ê·žëë ìì ì¡ìžì€ìë êŽì°®ë€ê³ ìê°í©ëë€.
ì í P = foo(0) ì í; // Pë ìì[]
ì í Q = foo ì í(true); // Që 묞ììŽì ëë€.
맀ê°ë³ì륌 ì íë³ë¡ ì°žì¡°í ì ìëë¡ íë ë°©ë²ì ëí ìŽ ë
Œììì ì€ì êž°ë¥ìë ëìŒíê² íì©íë ê²ìŽ ì¢ìµëë€.
컚í
ì€íž: ê°ì²Žì ëíŽ map
ì íšì륌 ì
ë ¥íê³ ì¶ìµëë€.
function map<T, F extends Function>(fn: F, obj: T): { [P in keyof T]: typeof F(T[P]) }
F
(ìŽëŠ fn
ì ìž)ë¡ íšì륌 ì°žì¡°í ì ìꞰ륌 ìíë ìŽì ë ìŽëŠì ì¬ì©í ì ìë 겜ì°ì
ëë€. ì륌 ë€ìŽ I' type MapFn<T, F extends Function> = { [P in keyof T]: typeof F(T[P]) }
ëŒê³ ë§í ì ììµëë€.
구ííêž° íšì¬ ìœê³ ì¬ì í ë§€ì° ì ì©í ì ìë ê²ì ë€ì곌 ê°ìµëë€.
const myFunc = () => ({ x: 10 });
type myType = returnof myFunc; // { x: number; }
ìŽë¡ ì ìŒë¡ ì íì ëª ìì€ ê¹ìŽë¡ ê°ì žì€ë €ë 겜ì°ìë ì°ê²°ë ì ììµëë€. ìŽê²¬ìë ì¬ë?
ížì§: @mpawelski ðê° ììì ìžêží ê²ì ë°©êž ê¹šë¬ììµëë€.
@dehli ì€ë²ë¡ëë êž°ë¥ììë ìëíì§ ììµëë€. ëë íì ë§€ê° ë³ìê° ë°í íìì ì¬ì©ëë ìŒë° íšìì ëë€.
@JsonFreeman ë€ìí ë°í ì íì OR
íšìì ì€ë²ë¡ëí ì ììµëê¹? ê·žëŠ¬ê³ ìŒë° íšì륌 ì¬ì©íë €ë©Ž ì íì ì§ì íŽìŒ í ì ììµëê¹?
ê°ë¥íê² ì§ë§ ìŒë§ë ì ì©í ì§ ëªšë¥Žê² ìµëë€. ì¬ëë€ì ë ìžë šë ê²ì ìíë ê² ê°ìµëë€.
ì ë§ ê³ íµì€ëœêž° ë묞ì ìŽê²ìŽ 곧 ìíëꞰ륌 ë°ëëë€.
ë§ì§ë§ íŽê²° ë°©ë²ìŽ ë ìŽì ìëíì§ ììŒë¯ë¡ íì¬ ë€ìì ì¬ì©í©ëë€.
// 0 argument function
export default function returnof<T>(fn: () => T): T;
// 1 argument function
// If no ambiguity simply infer the return type
export default function returnof<A, T>(fn: (a: A) => T): T;
// 1 argument function, with possible overload for the argument type.
// Explicitly set the type and use the correct overload
export default function returnof<A, T>(fn: (a: A) => T, a: A): T;
// ...
íšìì 곌ë¶íê° ììŒë©Ž ìžì륌 ì§ì í íìê° ììµëë€.
const hello = (arg: number) => 'World'
const helloReturnValue = returnof(hello)
type helloReturnType = typeof helloReturnValue // string
declare function hello(): void;
declare function hello(a: number): number;
const helloReturnValue = returnof(hello)
type helloReturnType = typeof helloReturnValue // void
const helloReturnValue = returnof(hello, 42)
type helloReturnType = typeof helloReturnValue // number
몚ë ì ìë ë€ì곌 ê°ìµëë€.
https://github.com/kube/returnof/blob/master/lib/returnof.d.ts
íë¡ì ížë¥Œ ì€ìŒìí€ì§ ìê³ ìœê² 묶ì ì ìë ìì NPM íší€ì§ 륌 ë§ë€ììµëë€.
Optional Genericsê° https://github.com/Microsoft/TypeScript/issues/2175 ìì ì ìë ê²ì²ëŒ ì¶ê°ëë©Ž ê°ëší ì ìžì íŽê²° ë°©ë²ìŽ íì©ë©ëë€.
type Return<T extends () => S, S> = S
ë€ì곌 ê°ìŽ ì¬ì©íììì€.
type helloReturnType = Return<typeof hello>
@mhegazy @JsonFreeman ìŽ êž°ë¥ì ëí ê³íìŽ ììµëê¹?
ìë
íìžì ì¬ë¬ë¶,
ëë ìŽ ë¬žì ì ëí ëììŽ ë ì ìë íŽê²°ì±
ì ê°ì§ê³ ììµëë€(ìŽë¯ž ì ìëìê³ ì ê° ëì³€ë€ë©Ž ì£ì¡í©ëë€) - 묞ì #13949ìì ì ìíìµëë€. ëë ê·ž ëšê³ìì typeof ì°ì°ìì ëíŽ ìì§ ëª»íì§ë§ ëŽ ì룚ì
ìŽ ë ìŒë°ì ìŽëŒê³ ìê°í©ëë€. Ʞ볞ì ìŒë¡ =MyType
ì ê°ì ìë¡ìŽ 구묞ì ëì
í©ëë€. ìŽ êµ¬ë¬žì MyType
륌 ì¬ì©íë 몚ë ê³³ìì ì¬ì©í ì ìì§ë§ ê°ì²Žë¥Œ MyType
ì íìŒë¡ ì ìžíë ëì ê°ì²Žì ì ì¶ë ì íìì MyType
ëŒë ì íì
ëë€. ì륌 ë€ìŽ ìŽê²ìŽ Vue êµ¬ì± ìì륌 ë§ëë ë° ì¬ì©íë ë°©ë²ì
ëë€.
function createData(){
return <=MyData>{
dataProp1: <string>null
}
}
function method1(){
let self: MyComponent = this;
console.log(self.dataProp1);
self.method2();
}
function method2(){
let self: MyComponent = this;
//dostuff
}
type MyComponent = MyData & MyMethods;
let componentOptions = {
data: createData,
methods: <=MyMethods>{method1, method2}
}
//todo: register component...
createData
íšìë ë€ì곌 ê°ìŽ ìì±í ìë ììµëë€.
function createData(): =MyData {
return {
dataProp1: <string>null
}
}
ìŽë€ ììŒë¡ë ìŒë°íí ì ìë ì ë§ ì¬ë¯žìë ë°©ë²ì ì°Ÿììµëë€.
const varWithRightType = (false as true) && some.deep.access()
type MyType = typeof varWithRightType;
ížì§: ê·žë§ ììŒìžì ìŽê²ì ì¬ê°í ì¡°íì ëë€
@johnfn ìŽê²ì ê°ëší 겜ì°ì ì¬ë¯žììŽ ë³ŽìŽì§ë§ íšìì ìŒë¶ 맀ê°ë³ìê° íìí ê²œì° ë€ì곌 ê°ìŽ ì¶ê° ìì ì ìííŽìŒ í©ëë€.
const stateProps = (false as true) && mapStateToProps({} as any);
ì ë mapStateToProps
íšììì props ì íì ê°ì žì€êž° ìíŽ ì í ì¶ë¡ ì ì¬ì©íë €ê³ í ë React & Reduxì í¹í ì ì©í ë€ë¥ž íŽê²° ë°©ë²ì ì¬ì©íê³ ììµëë€. ê·žë¬ë©Ž ë ìŽì ì ì§ êŽëŠ¬ê° ë²ê±°ë¡ê³ ì€ë¥ê° ë°ìíêž° ì¬ìŽ Redux connect
ì ìíŽ ì£Œì
ë Propsì ìží°íìŽì€ë¥Œ ìëìŒë¡ ì ìžíê³ ì ì§ êŽëŠ¬í íìê° ììµëë€.
ìŽ íŽê²° ë°©ë²ì ë€ë¥ž ì¬ì© ì¬ë¡ì ëíŽ ì£ŒìŽì§ íšì ìëª
ë íë¥íê² ì²ëŠ¬í©ëë€.
typeof
ì°ì°ì "React & Redux" ì¬ì© ì¬ë¡ì ì:
ìë ìì ììë TypeScriptì ì¶ê°íë©Ž ë§€ì° ì ì©í íšì ì ìžìì ì íì íìíêž° ìíŽ
typeof
ì°ì°ì륌 ì¬ì©íë ìŒë°ì ìž ì€ì íë¡ì íž ì¬ì© ì¬ë¡ë¥Œ 볎ì¬ì€ëë€.
import { returntypeof } from 'react-redux-typescript';
import { RootState } from '../../store';
...
const mapStateToProps = (state: RootState) => ({
currencies: CurrencyRatesSelectors.getCurrencies(state),
currencyConverter: storeState.currencyConverter,
});
const stateProps = returntypeof(mapStateToProps);
type Props = typeof stateProps & typeof dispatchToProps;
type State = {};
class CurrencyConverterContainer extends React.Component<Props, State> {
...
ì¶ì²: https://github.com/piotrwitek/react-redux-typescript-patterns#react -connected-components
@kube ì ì룚ì 곌 íší€ì§ https://github.com/kube/returnof ê° ììëë¡ ìëíë ê² ê°ìµëë€! ð
í . returnof
ê° .d.ts
íìŒìì íí êž°ë° map()
ì ì
ë ¥íë ë° ëììŽ ëììŒë©Ž íì§ë§ ííì ìžìŽì ëí ìì¡Žì±ì ê°ìí ë( const
ë ì£Œë³ ì»ší
ì€ížìì ì¬ì©í ì ììµëë€. ), ëë ê·žê²ì ëí ëì ì¬ì© ì¬ë¡ê° ì ìŽë ë ë³µì¡í ê¹ëŽ ëë €ìí©ëë€.
ížì§: ì§êžê¹ì§ ì íì ì ë€ëŠìŽ ë³í© ë ê² ê°ìµëë€. ìŠ, @kube ì ì ìžì ì í ìžìŽ ì ì© ë²ì ( type Return<T extends () => S, S> = S
-> type helloReturnType = Return<typeof hello>
)ìŽ ì€í ê°ë¥íê² ë ê²ì
ëë€. :ë
ìì : ìëì, Ʞ볞 ì ë€ëŠ ê°ì ëí ë³í©ë ì§ìì ì ë€ëŠì ìŒë¶ë¥Œ ì§ì íë ê²ì íì©íì§ ìë ê² ê°ìµëë€. Return<typeof hello>
ë Generic type 'Return' requires 2 type argument(s).
ì€ë¥ë¥Œ ìì±í©ëë€.
@tycho01 ë€, 묞ì ê° íŽê²°ëì§ ìì ì€ë§íìµëë€.
ì íì ìŒë° ì í ì¶ë¡ ì ëí êŽë š 묞ì 륌 ìŽë¯ž ìŽììµëë€.
ìŒë°ì ìŒë¡ ë믞 ì°ë¹ìžíž íšìì ì í ì¶ë¡ ì ì¡°í©ì íµíŽ íšìì ë°í ì íì ì»ì ì ììµëë€.
ì£Œë³ function returnTypeOf<RT>(fn:(...rest:any[])=>RT):RT {return void 0};
ë¡ì»¬ var r = returnTypeOf(someFunction);
ë undefined
ê°ì ì»ìµëë€.
ê·žë¬ë íŽë¹ ë°í ì íì ì¬ì¬ì©íë €ë©Ž 캡ì²íŽìŒ í©ëë€. ê·žëì ì°ëŠ¬ë ì²ì ììíë ê³³ìŒë¡ ëìê°ëë€.
type RT = typeof r;
ì²ìì typeof
ì ê°ë
ì íì¥íì¬ returntypeof
#$ 륌 íì©íê±°ë typeof fn(a,b,c,...)
ìì ìŽ ì¬ì©ë²ì ë ì ì¶ë¡ í ë€ì ë€ë¥ž ìëª
ë°í ì íì 캡ì²í ì ìë€ë©Ž íšì¬ ë ì¬ìž ê²ì
ëë€. . ìŽ ë°íí ìŽíŽë ìŽë¯ž TSìì ëŽë¶ì ìŒë¡ ìíë©ëë€.
typeofexpression ()
ë ì í ì°ì°ê³Œ íŒí©ë ìŒì¢
ì ë°í ì í ì¬ê·ì
ëë€. ì:
type E = typeofexpression (f(1) + g("x"))
~ìŽë€
type E = typecomprehensionof (typeof f(1) + typeof g("x"))
ë€ì ì€ íëì²ëŒ ìŽíŽë ì ììµëë€.
type E = typecomprehensionof (string + string)
ìŠ string
type E = typecomprehensionof (string + number)
ìŠ string
type E = typecomprehensionof (number + number)
ìŠ number
ìŽê²ìŽ ëŽë¶ì ìŒë¡ ìŒë§ë ìŽë µê³ ì±ë¥ ë¹ì©ì ëìê² ìë €ì§ì§ ìììµëë€.
ížì§íë€ ------------------------------------------------- ----------
ì¶ê°íë €ë ... ìŽê²ì Function.bind, Function.apply, Function.callì ì¬ì©íŽìŒ íë 몚ë ì¬ëìê² í¹í ì€ìí©ëë€. ìëíë©Ž ìŽë€ì íì¬ any
ì íì ë°ííê³ ìŽë ì§ìì ìŒë¡ ì íìŽ ëìŽìŒ íšì ì믞íêž° ë묞ì
ëë€. ì í ê²ì¬ íë¡ìžì€ìì ë¹ ì§ì§ ìëë¡ ì£Œìì ë¬ììµëë€.
íšì ìžìì ë°í ì íì ì°žì¡°í ì ìë€ë ê²ì ... bliss ...
@poseidonìœìŽ
íšì ìžìì ë°í ì íì ì°žì¡°í ì ìë€ë ê²ì ... bliss ...
ëë íì¬ì typeof <expression>
ê° ë ì¢ìŒë©° ë°í ì í 묞ì ë #12342ìì ìŽë¯ž ë€ë£¹ëë€.
ì€ëª
ìì ìŽë¬í ì¬ì©ë²ì 구ë³íë ìëšìŒë¡ typeofexpression
ë° typecomprehensionof
륌 ì¬ì©íìµëë€. ì€ì 구묞ìŒë¡ typeof (expression)
륌 ì íží©ëë€.
ëŽ ìì ì ííìì ì íì ìŽíŽíë €ë©Ž íšìì ë°í ì íì ìŽíŽíŽìŒ íë€ë ê²ì
ëë€... f(1)
ë ííìì
ëë€. #12342 ë ìŽë° ììŒë¡ êŽë šëìŽ ììµëë€. ê·žê²ë€ì ìíž ë°°íì ìŽì§ ììµëë€.
ì°ëŠ¬ë ìŽë¯ž ë³ìì ëíŽ typeof
륌 ìíí ì ììŒë©° ííìì ë³ìì íšìì ëí ì°ì°ìŽë¯ë¡ ë€ì ì구ì¬íì íšìì ì íì ë°íí ì ììŽìŒ íê³ ... ê·žëŠ¬ê³ ì í ê·ì¹ì ë°ëŒ 결곌륌 ìŽíŽí ì ììŽìŒ í©ëë€. .
ì¬ì€ ì¢ì ì§ì ì ëë€. #12342ê° ìíë 묞ì ë ì ë€ëŠ ì íì ëí ìŒì¢ ì ìì±ê³Œ ê°ì ê²ìŒë¡ ë°í ì íì ì¡ìžì€íë ë°©ë²ìŽë¯ë¡ êŽê³ë¥Œ ì못 ìŽíŽíìµëë€.
ì ìììì ê°ìŽ typeof
íšì ížì¶ì ííìì ì¬ì©íì§ë§ 맀ê°ë³ì ëì ì íì ì§ì ì¬ì©íë ê²ì ìŽë»ìµëê¹?
ì
function myFunction<T>(param1: T, param2: string, param3: number): T & {test: string} {
// ...
}
type ResultType = typeof myFunction({hello: string}, string, number)
// ResultType is: {hello: string} & {test: string}
ìŽê²ì ížì¶ ëŽìì typeof륌 ì¬ì©íì¬ ë¡ì»¬ ë²ì ë³ì ì íì ì¬ì©íë ê²ì ë§ì§ ììµëë€. ì:
type ResultType = typeof myFunction(typeof obj, string, number)
// ResultType is: typeof obj & {test: string}
ìŽê²ì ì£Œë³ ì»ší ì€ížìì ìëíê³ ìŒë°ì ìŒë¡ ë ì ì°íŽ 볎ìŽêž° ë묞ì ìë ì ìë³Žë€ ì¡°êž ë ëì ê² ê°ìµëë€. ëìê² ê·žê²ì ëí ì°ëŠ¬ê° ì€ì ë¡ íšì륌 ížì¶íë ê²ìŽ ìëëŒ ë°í ê°ì ì íì ë°ííë €ê³ íë€ë ê²ì ë ëª ííê² í©ëë€.
ëŽ ê°ëší 겜ì°ì ìŽë»ê²íëì§ :
interface IAlertMessage {
addedAt: number;
text: string;
type: "error" | "warning" | "info" | "success";
}
declare let alertMessageInterface: IAlertMessage;
const messages: IAlertMessage[] = [];
function addMessage(text: string, type: typeof alertMessageInterface.type): void {
messages.push({addedAt: new Date().getTime(), text, type});
}
addMessage("something", "info"); // <- OK - and also has intellisense for the second parameter (after typing first " of the second parameter, press Ctrl+Space in VSCode)
addMessage("something", "fatal"); // <- Compilation error : error TS2345: Argument of type '"fatal"' is not assignable to parameter of type '"error" | "warning" | "info" | "success"'.
ìì ëŽì©ì ìží°íìŽì€ ì첎ì ë©€ë²ììë ìëí©ëë€.
declare let myIface: MyInterface;
interface MyInterface {
prop1: {
big: {
complex: {
anonymous: { type: {} }
}
}
},
prop2: typeof myIface.prop1.big.complex.anonymous;
}
type ...
declare let ...
륌 ì¬ì©íë ìŽì ì ì¶ë ¥ .js íìŒì ì묎 ê²ë ìì±íì§ ìëë€ë ê²ì
ëë€.
@varadero ìŽê²ì íšì ížì¶ì ë°í ì íì ê²ìíë ë¹ë©Ží 묞ì 륌 íŽê²°íì§ ëª»í©ëë€. TypeScript 2.2ë¶í° ì§ìëë êž°ë¥ìž ì íì ìì± ì íì ê²ìíë ê²ë¿ì ëë€.
ê·žê²ì ì€ì ë¡ (ê°ì§) ê°ì ìì± ì íì ëë€. 컎íìŒë¬ë "ììí" ì í ëë ìží°íìŽì€ì íšê» typeof륌 ì¬ì©íë ê²ì íì©íì§ ììŒë©° ê°ì ëíŽìë§ ìëí©ëë€.
ìŽê²ì ììŒë©Ž ì¢ì ê²ì ëë€!
type KEYOF<T extends any[]> = keyof T[0]
ê° ìŽë¯ž ì¡Žì¬íêž° ë묞ì function myFunc<T, K extends KEYOF<T>>(type: K)>{ }
ë° myFunc([(r: string) => r])
륌 ê°ì íë©Ž $ typeof T[0]('something')
ë ìŽ êµ¬íììë ì ìëí©ëë€( typeof T[0]('something')
ì ëí 묞ììŽ ë°í). ?
ìŽê²ì ë€íì± this
ì íšê» ê°ë ¥í ê²ì
ëë€.
ìŽê²ìŽ ìŒìŽë ìê°ì ëë€!
ìŽ ì€ë ë륌 ë€ì ìœìŒë©Žì ì°ëŠ¬ê° typeof
구묞ìŒë¡ 묎ìì íê³ ìëì§, ì ê·žë°ì§ ìŽíŽíë €ê³ íìµëë€.
ë¶ëª
í, ìŽë¯ž 구íë ì¬ìí typeof foo
겜ì°ìë foo
ì íì ì ê³µí©ëë€. ( pet is Fish
ë í¹ì 구묞ì ì¬ì©íë ë° ë©ŽììŽ ìë€ê³ ìê°í©ëë€.)
íì¬ ì ììì ìŽ í€ìëê° ìííŽìŒ íë ìì
ì ëí ëì íì¬ ìœêž°ìì í€ìë ì첎ë íì¬ ìííë ê² ìŽìì ìííì§ ììŒë©° íì¬ ì ìì ì€ì ë¡ typeof
í€ìëì êŽë šìŽ ììµëë€.
ììì ìžêží 겜ì°ì ì€ìíêž° ë묞ì ìŽ ë¬žì 륌 ì êž°í©ëë€. ì¬êž°ì ì°ëŠ¬ë ê°ìŽ ìë ì íìŒë¡ ì ì¥ë íšì( type
륌 íµíŽ ëë ìŒë°ìŒë¡)륌 ì ì©í©ëë€.
ìŽë¥Œ ê°ìí ë typeof fn<A>(string)
ë ì í ìì€ìì ì¬ì©íêž° ìíŽ ííì ìì€ ë³ì fn
typeof
#$ê° íìíê³ ë€ë¥ž íížìŒë¡ë Fn<A>(string)
$ê° íìíë€ê³ ê°ì í©ëë€. , Fn
륌 íšì륌 í¬íšíë ì ë€ëŠìŒë¡ ì¬ì©íë©Ž ìŽë¥Œ íìë¡ íì§ ììŒë¯ë¡ typeof
íì ììŽ ì¬êž°ì ì ì í ë°í ì íì ì»êž° ìíŽ 'ì ì©'í ì ììµëë€.
ìŽ íŽììì ì°ëŠ¬ë Fn(...)
ìž íšì ì í ìŽí typeof fn<...>(...)
íšì Fn<...>(...)
ì íìží©ëë€ typeof fn(...)
늬í°ëŽ ((foo: Foo) => Bar)(Baz)
/ + ì ë€ëŠ. ê·žë ì§ ììŒë©Ž 공격 ê³íìŽ ê·žëë¡ ì ì§ëìŽìŒ í©ëë€.
ìë§ë ëë ì¬ë¬ë¶ìŽ ìŽê²ì ìŽë»ê² 볎ëì§ ì못 íŽìíê³ ìì ì ììµëë€. ìë§ë ì íì ì ì¥ë íšìë ê³ ë €ì¡°ì°š íì§ ììì ê²ì ëë€(ëŽê° ìžêžíì§ ììêž° ë묞ì). ìŽë 쪜ìŽë , ëë ê·žê²ìŽ íìží ë§í ê°ì¹ê° ìë€ê³ ìê°íë€.
íšì ìì© íë¡ê·žëšì ë°ííë ê²ìŽ typeof
ì ëí ë ë€ë¥ž ìë¯žë¡ ì ì€ë²ë¡ëê° ëë€ë©Ž, íŽëì€ ìì±ì륌 ëª
ííê² íê³ ííì ìì€ ë³ì륌 ì í ìì€ìŒë¡ ë€ìŽì¬ëŠ¬ë ê² ìžìë( íí ìì€ typeof
ì ìž), ìŽ ì€ë ëì ëª ê°ì§ ìŽì ì§ë¬žìì ìŽë¯ž ì§ì íë¯ìŽ ì ì°šì ìŒë¡ ë ë³µì¡íŽ 볎ì
ëë€.
ížì§: ì ë€ëŠ ì íì ìŽë¯ž ì ë€ëŠë ê°ì§ ì ìë íšì ì íì ë°íí ì ììµëë€. ìŽê²ì ë ë€ë¥ž ììŽìŽ GetFn<A><B>()
ê° ë ê²ìì ì믞íë©°, 첫 ë²ì§ž ì ë€ëŠ ìžížë ì ë€ëŠ ì í ížì¶ì ìíê³ íìë íšì ížì¶ì ìí©ëë€. GetFn<A><B><C>()
ë ìëì§ë§ GetFn<A><B>()<C>()
ë í©ë²ì
ëë€. ê·žë¬ë ìŽì ê²°ë¡ ì ë³ê²œëì§ ìììµëë€. 몚ë ì íì íšì륌 í¬íší ì ììŒë¯ë¡ (ì ì¬ì ìŒë¡) íšìë¡ ì ì©ë ì ììµëë€.
ížì§ 2: X<Y>()
ì ë¶íí 몚ížíšìŽ ìë€ë ê²ì ë°©êž ê¹šë¬ììµëë€. ìŽì X
ë íšì ì íì ë°ííë ì íìŽ ë©ëë€.
X
ê° ì ë€ëŠìŽ ìë ê²œì° ìŽê²ì ë¶ëª
í©ëë€. <Y>
ë íšì ížì¶ì ìí©ëë€.X
ê° ì ë€ëŠìŽê³ 맀ê°ë³ìê° íìí ê²œì° ìŽê²ë ë¶ëª
í©ëë€. ìŽë ì íì ìíë©° íšììë ì í 맀ê°ë³ìê° ì ë¬ëì§ ììµëë€.X
ì ì íì ì ë€ëŠìŽ ììŒë©Ž ìŽë 몚ížíŽì§ëë€.X
ìë ì í 맀ê°ë³ìê° ì ë¬ëì§ë§ íšìë ì ë¬ëì§ ììµëë€.X
ë Ʞ볞 ì í 맀ê°ë³ì륌 ì¬ì©íëë¡ ëšê²šëê³ <Y>
ë ëì íšì ížì¶ì 맀ê°ë³ìíí©ëë€.ì¬êž°ì ê°ì¥ ì¢ì íŽê²°ì± ìŽ ë¬Žììžì§ ìì§ íì€íì§ ììµëë€.
<>
륌 ì¬ì©íë ê²ì
ëë€. ê·žë¬ë ìŽê²ì íêž°ì ìž ë³íê° ë ê²ì
ëë€.@icholy : ì, ìŽë¬í ížì§ì ê·íì ìì ì ì¶ê°ë¡ ì¶ê°ëê³ ìë€ë ê²ì ìëë€.
ížì§ 3: ì¢ì, ìŽ êž°ë¥ì ìŽì ëŽ ìì늬ì€ížì 맚 ìì ììµëë€. ì¶ë¡ ì ëí ìí¥ ìž¡ë©Žìì ì격ìŒë¡ ê°ê¹ìŽ ì ê·žë ìŽëë ììµëë€.
@icholy : ê°ëší ë§íŽì 'íšì'ê° ìŒë°/ì íì ììŒë©Ž ì¬ì í typeof
륌 ìì±í ê¹ì?
ìŽ ìì ìŽ ìíëìŽ ì€ë²ë¡ëì ì¬ë°ë¥Žê² ìíž ìì©íë©Ž ì€ì ë¡ "ê°ë³" íšì륌 묎ë£ë¡ ì ê³µí©ëë€(>1 arity륌 ââê°ë ëì 컀늬 ì²ëŠ¬ëš). ìŒë¶ Ʞ볞 ì¬ë¡ 곌ë¶íì íšê» 곌ë¶í ì€ íëì ì ì©. ìŽê²ìŽ Haskellìì ìíëë ë°©ììŽë©° TypeScriptì ììŒë©Ž ë©ì§ êž°ë¥ìŽ ë ê²ì ëë€.
@masaeedu : í¥ë¯žë¡ê² ë€ëŠœëë€. ê·žëŠ¬ê³ ì, ì€ë²ë¡ëë íì€í ìŽ ì ìì ë§€ì° í¥ë¯žë¡ê² ë§ëë ê²ì
ëë€. any
íŽë°±ìŽ í¬íšë ë€ìí ìµì
ì ëí íšíŽ ìŒì¹ì ì¬ì©í ì ììµëë€. ê·žë° ì í ê²ì¬ë ìì§ ì í ìì€ìì ê°ë¥íì§ ìììµëë€.
ëë Haskellë³Žë€ Ramda륌 ë ë§ìŽ ì¬ì©íë€ë ê²ì ìžì í ê²ì ëë€. ê·žë¬ë ê·ž 배겜ìì ëë 칎ë ê° ì¶ê° ìžì륌 ì²ëŠ¬íêž° ìíŽ ê²°ê³Œë¥Œ ë°íí ì§ ìëë©Ž ë€ë¥ž íšì륌 ë°íí ì§ 'ìììŒ'íêž° ë묞ì ìŒë°ì ìŒë¡ 컀ë§ìŽ ê°ë³ íšìì ì ê²°í©ëì§ ìëë€ê³ ìê°íìµëë€.
Object.assign
( &
ë Overwrite
ì ê°ì ìžë¶ ì 볎 걎ëë°êž°)ì ê°ì ê°ë³ íšìì ëíŽ ìŽ ììŽëìŽê° ìëíë ë°©ë²ì ëíŽ ìì¬ ìœë륌 íìí ì ììµëê¹? ëŽ PoCìì R.mergeAll
)?
@tycho01 ì ë ë€ì곌 ê°ì ìœë륌 ê°ì§ê³ ëììµëë€.
interface Pop<TVarStack extends VarStack> {
(a: TVarStack["head"]): Pop<TVarStack["tail"]>
}
interface VarStack<THead = any, TTail extends (void | VarStack) = any> {
head: THead
tail: TTail
<TNew>(a: TNew): VarStack<TNew, this>
(): (a: Pop<this>) => any
}
// Figure out implementation later :)
let stack: VarStack<void, void>;
const pop = stack(new Date())(10)("Bob's")("your")("uncle")()
// a, b, c, d, and e are well-typed
pop(a => b => c => d => e => {
// Need this because can't figure out how to encode base-case in Pop recursion
return stack
})
VarStack
ë ììì ìì ìŽêž°ì¢
ìžì륌 ì ê³µí ì ìê³ ì í ìì€ìì ì¬ê·ë¥Œ ì¬ì©íì¬ ì°êŽë ì í ì 볎륌 충ì€íê² êž°ë¡íë€ë ì ìì "ê°ë³" íšì ì íì
ëë€. ë¶ííë TypeScriptë Haskell곌 ê°ì ë°©ììŒë¡ ì í ìì€ìì ë³í ë° íšíŽ ìŒì¹ë¥Œ ì ì§ìíì§ ììµëë€.
typeof
ì ì¡ìžì€í ì ìë€ë©Ž Pop
ì ëí Ʞ볞 ì¬ë¡ 묞ì 륌 íŽê²°í ì ììµëë€ returnof(overloadedFunction(T))
ì í ìì€ìì ìŒì¹í©ëë€.
@tycho01 Object.assign
ì ëíŽìë ì íí í ì ììµëë€. ìëíë©Ž ì ê° ë§íë¯ìŽ ìŽê²ì 컀늬 íšììë§ ìëíì§ë§ ëëµì ìŒë¡ ìëíë 컀늬 assign
íšì륌 ë§ë€ë €ê³ ë
žë ¥í ê²ì
ëë€. ê°ì ë°©ììŒë¡.
ì륌 ë€ìŽ (a: string) => (b: number) => void
ê° Func<string, Func<number, void>>
ì ëí ì€íìŽê³ (a: string, b: number) => void
ê° Arity<number, Arity<string, void>>
ì ëí ì€íìŽ ëëë¡ ì í ëìíì ìœê° ìŒë°ííìŒë©Ž í©ëë€. ê·žë° ê². ê·žë° ë€ì ìë¡ìŽ í¥ë¯žë¡ìŽ êž°ë¥ì ë§ìŽ ì»êž° ìíŽ ì íì ë³ííë ë²ì© ëêµ¬ê° íìí©ëë€.
ížëŠ¬í í¬ì€ížì ëíŽ ëªšë ì¬ê³Œë늜ëë€. @tycho01 ë€ìì "variadic" 칎ë assign
ì
ëë€.
interface Assign<TCurr extends {} = {}> {
<TAdd extends {}>(a: TAdd): Assign<TCurr & TAdd>
(): TCurr
}
let assign: Assign = undefined // implement somehow
const result = assign({ foo: "bar" })({ baz: 42 })()
@masaeedu : í, ê·žëì ê°ìêž° êž°ë¥ìŽ ìë ê² ê°ìì. :) ê°ë³ì ìŽì§ ìì(?) ìžìê° ììŒë©Ž ê·ž ë¶ë¶ìŽ ë ìŽë €ìì§ ìë ììµëë€.
ëë ê·ž ììŽëìŽë¥Œ ì¢ìíë€. ëë íì€í ìží°íìŽì€ì ë°©í¥ì ëíŽ ë§ìŽ ìê°íì§ ìììµëë€.
íì§ë§ íìŽíì ëí JS륌 ë³ê²œí ì ìë€ë©Ž ìë§ë TC39ìê² Object.assign
륌 ê°ë³ì ìŽì§ ìì mergeAll
ë¡ ë³ê²œíëë¡ ìì²í ê²ì
ëë€. :ë
ì§êžê¹ì§ ì€ì ë¡ íšì륌 ì¬ì©íì¬ ìëí ê²ê³Œ ê°ì ìŠë¶ êž°ë° ë°ë³µê³Œë ë€ëŠ ëë€(#17086)... íì§ë§ ìŽë 쪜ìŽë ì ë ìŽ ì ììŽ ì ê° ë³ž ë€ë¥ž ì ìë³Žë€ ë í° ìí¥ì ë¯žì¹ ê²ì ëë€.
@tycho01 ê°ë³ íšì륌 ê³ ì ë arity íšìë¡ ë°êŸžëë¡ ìì²íë©Ž JS(ëë ìµìí êž°ì¡Ž JS ìì§ ë° ìœë)ì ì ì©ëë 컀늬 íšìë ë°ë³µ ì í늬ìŒìŽì ì ë°íì ë¹ì©ìŽ ë€êž° ë묞ì ë§ì êŽì¬ì ëì§ ëª»í ê² ê°ìµëë€. ìë§ë ê³ ëë¡ ìµì íëìŽ ìì§ ìì ê²ì ëë€. ëì ì TypeScriptê° arity > 1 íšìì ëí ì íì ì¬ê·ì ìŒë¡ ìœê² êµ¬ì¶ ë° ë¶íŽí ì ìëë¡ íë ê²ìŽ íìíë€ê³ ìê°í©ëë€. ìŽ ëªšë ê²ìŽ #5453ìŒë¡ ëìì€ë ê² ê°ìµëë€.
ë€ë¥ž ì¬ëë€ì C++ì ë§€ì° ì ì¬í êž°ë¥ìŽ ìë€ë ê²ì ë°°ì°ë ê²ìŽ í¥ë¯žë¡ìž ì ììµëë€: decltype(expression)
ìŽ êž°ë¥ìŽ TypeScriptì ì ì©ë©ëê¹?
ëë ìžìê° ííììž ìë ì ìë íìì ë§€ì° ì ížíì§ë§ ííì ìì¹ì ì íìŽ ìë í¹ì 구묞ì ì¬ì©íë €ë TS íì ìëë 몚ë ê²ì ë³µì¡íê² ë§ë€ê³ ìžìŽë¡ì ìë¥ì ì§ì°ìíµëë€.
ì°ëŠ¬ë ìŽ ì£Œì 륌 ê³ì ì ì§íŽìŒ í©ëë€.
ìŽ ì ìì ìŒë¶ëŒë 구íí ì ìë€ë©Ž ì ë§ êž°ì ê²ì
ëë€. ìŠ, ìŽ ì±êž:
type A = typeof anotherVariable
. ìŽ í ì€ìŽë©Ž 몚ë ê²ì í ì ììµëë€. interface B extends A
, <B & A>
: B & A
ë±
ëë Reactìì ìŽë° ì¢ ë¥ì ì¬ì© ì¬ë¡ë¥Œ ë§ìŽ ë³Žê³ ììµëë€. ê³ ì°š êµ¬ì± ìì륌 ë§ë€ ë êµ¬ì± ìì íŽëì€ ì ìžì íì¬ HOCìì ììíë ê²ìŽ íšì¬ ë ìŽë µìµëë€.
ëŽê° í ìŒì ë ê°ì íŽëì€ë¥Œ ë§ëë ê²ì
ëë€. í íŽëì€ë React.Component
륌 íì¥íê³ ëªšë ì¶ê° ë©ìë륌 ì¶ê°íë ë°ë©Ž HOC íšì ëŽë¶ì íŽëì€ë render()
륌 ì¡°ìí©ëë€.
@blindbox type A = typeof anotherVariable
ë ìŽë¯ž ìëí©ëë€:
var data = [1, 2, 3].map(v => ({ raw: v, square: v * v }));
function checkItem(item: typeof data) {
// item is Array<{ raw: number; square: number; }>
}
@Igorbek ìì°, ë§ìµëë€.
ì¢ì, ëë ê·žê²ìŽ ëŽ ëìì ìëíì§ ìë ìŽì 륌 ìì ëìµëë€.
ìŽê²ì ìëíì§ ììµëë€
interface B {
thisIsB: boolean
}
const typeTest = (type: any) => {
return 1 as any as App & B
}
type A = typeof typeTest(1)
declare const aVal: A; // aVal's type isn't of type App & B, but something else.
ê·žë¬ë ìŽê²ì ìëí©ëë€.
interface B {
thisIsB: boolean
}
const typeTest = (type: any) => {
return 1 as any as App & B
}
const typeTestVal = typeTest(1)
type A = typeof typeTestVal
declare const aVal: A; // aVal's type is of type App & B!
ì, 묞ì ë ì ë€ëŠ íì ìžì륌 ì¬ì©íŽìŒ íë 겜ì°ì ê°ì í¹ì ì¬ì© ì¬ë¡ììë ì¬ì©í ì ìë€ë ê²ì ëë€.
function someFunctionWithComplexReturnTypeThatUsesGenerics<T>(item: T) { ... }
// it is impossible to work this around because there's no chance to create a fake variable that would be parameterized by T
function use<T>(item: typeof someFunctionWithComplexReturnTypeThatUsesGenerics<T>(item)) { ... }
@ìŽê³ 륎벡 :
ëë ìžìê° ííììž ìë ì ìë íìì ë§€ì° ì ížíì§ë§ ííì ìì¹ì ì íìŽ ìë í¹ì 구묞ì ì¬ì©íë €ë TS íì ìëë 몚ë ê²ì ë³µì¡íê² ë§ë€ê³ ìžìŽë¡ì ìë¥ì ì§ì°ìíµëë€.
ê·žëì ê·žë€ìŽ ê·žê²ì ìŽ ìŽíë¡ ì°ëŠ¬ë 묞ììŽê³Œ ì«ìì ëí 늬í°ëŽì ì»ììµëë€. ìŠ, ìí©ìŽ ì¢ ë 몚ížíŽì§ê³ ììµëë€. ë ë€ ìëí©ëë€. 늬í°ëŽ ë°°ìŽê³Œ ê°ì²Žë ì ì¬íê² ì í íêž°ë²ê³Œ ì ì¬íê² ë³Žì ëë€.
ë°ëŒì ë³ì, ì ë€ëŠ, êž°í ì í곌 ê°ì ê°/ì íë ì ì¥íìµëë€. ì ì©í ì 볎륌 ì»ìŒë €ë©Ž ì¬êž°ìì ìŒë¶ë§ íŽê²°íë©Ž ì ë©ëë€.
ì¬êž°ì ì í êž°ë° ì ê·Œ ë°©ìì ëí ì¢ì ë
Œê±°ë ìŽë¬í íŒí©ì íì©íë ê²ìŽ ì í ìì€ìì 묎ë£ë¡ ì ê³µëë€ë ê²ì
ëë€. ìŠ, ì í ìì€ìì ìŽë¯ž typeof myVar
ëŒê³ ë§í ì ììµëë€. ìŠ, ìŽ íšì 'application'ìŽ ì í ìì€ì ì¶ê°ëë©Ž ì ì¥ë ì í곌 ìŒë° ë³ì륌 몚ë ìëìŒë¡ ì°ê²°í ì ììµëë€. .
ìë ì ìë ì ê·Œ ë°©ìì ëí ì¶ê° ìê°ì ë³Žê³ ì¶ìµëë€. íì€í, ê·žê²ì ì í ìì€ì ì¡°êž ë ë
žì¶ìí€ë ìí ì í ì ììµëë€. JS êž°ë° ì°ì°ì( !
&&
||
+
-
*
/
instanceof
) ë° TypeScript í¹ì ì°ì°ì(ìŽì€ì
ì°ì°ì !
).
ìŽë¬í JS ì°ì°ìì ëí 묞ì ë ... íŽë¹ 늬í°ëŽ 결곌 ì íì ìì±íêž° ìíŽ ëŠ¬í°ëŽìì ìì
í ì ìëë¡ íì©íë ê²ìŽ íì¬ ë²ì( ref )륌 ë²ìŽë ê²ìŒë¡ ê°ì£Œëêž° ë묞ì ê·žëë¡ ì í ìì€ììë ê±°ì ìžëªšê° ììµëë€. -- expression -level 1 + 1
ë number
ì íì ìì±íê³ ë€ë¥ž ì íë ì ì¬í©ëë€.
ìŽê²ì ìŒëì ëê³ ëë ì í êž°ë° ì ìì ëíŽ ë€ì ì€ë§íìµëë€.
ìŽ êž°ë¥ìŽ TypeScriptì ì ì©ë©ëê¹? [...] ì°ëŠ¬ë ìŽ ì£Œì 륌 ê³ì ì ì§íŽìŒ í©ëë€.
ëë ìŽ ì ìì ìì ìŠì ì ëí ë³Žë€ ìŒë°ì ìž íŽê²°ì± ìŒë¡ ì ìíì§ë§ ì±ê³µì ì íì ìŽììµëë€.
@tycho01 typeof
ì ííì êž°ë° ë³íì ëí ëŽ ì£Œì¥ì @yortus ê° ìë ìžêží ê²ê³Œ ê±°ì ê°ìµëë€.
typeof
(ì í ìì¹ìì)ë ìŽë¯ž ííììŒë¡ ìëíì§ë§ ëšìŒ êž°ížë¥Œ íì©íëë¡ ì íë©ëë€. ë°ëŒì ì í ëë ìì¬ ížì¶ì ìëœíë©Ž ííì ë° ì í ìžìë íšì¬ ë ë§ì 구묞 ë¶êž°ìž íšì¬ ë ë³µì¡í êµ¬ë¬žìŽ ëì
ë©ëë€.(undefined as any as <any arbitrary type can be here>)
)ì ì¬ì©í ì ììŒë¯ë¡ ìµìí ì í곌 ëìŒí ííë ¥ì ê°ì§ë§ ëë¡ë ì í ìì€í
ì ííììŒë¡ ííí ì ìë ì íìŽ ë¶ì¡±í©ëë€(spread ë° rest ì íì ìŽíì ëì
ëììµëë€. íŽë¹ ííìŽ ì°©ë¥íìµëë€).promised
PRì ê·ž ì ì ìë €ì£Œì @tycho01ë ê°ì¬í©ëë€. (ì ë ì€ì ë¡ ê·íì ì견ì ë£ê³ ì¬êž°ì ììµëë€), ìŽë ì ë§ ê°ëšíê³ ìŒë°ì ìž êž°ë¥ìŽ êµœì§ ìê³ ë§€ì° ì°ìí ë°©ììŒë¡ íšì¬ ë ë³µì¡í ìë늬ì€ë¥Œ ë€ë£° ì ììì 볎ì¬ì€ëë€. ìžìŽì ëí ë§€ì° êµ¬ì²Žì ìž íëìŒë¡.
ëë íì¥ë typeof
륌 맀íë ì í/ keyof
곌 ê°ìŽ ì í ìì€í
ííë ¥ì ëí ì€ì ê²ì 첎ìžì ë¡ ëŽ
ëë€.
@Igorbek : ììží ì€ëª íŽì£Œì ì ê°ì¬í©ëë€. ìŽëì ìëì§ ìê² ìµëë€. ìë§ë ìŽ ë ê°ì§ ì ê·Œ ë°©ìì ìë¡ ë€ë¥ž ì¬ì© ì¬ë¡ë¥Œ ì ê³µí ê²ì ëë€.
íì¬ TS(ëë Playgroundì 2.3.3
)ê° ìŽë¯ž ë§ì ìë ìë늬ì€ë¥Œ ìëíê² í ì ììŒë¯ë¡ ìë ê²ìë¬Œë³Žë€ ìë ì ìì íì¬ ê°ì¹ë¥Œ ë ì 볎ì¬ì£Œê³ ìë€ê³ ìê°í©ëë€.
// I have a strongly-typed collection but the element type is anonymous/unknown, how can I reference the element type? (#3749)
// Mapping to a complex anonymous type. How to reference the element type?
var data = [1, 2, 3].map(v => ({ raw: v, square: v * v }));
declare function checkItem(item: typeof data[0]): any
// ^ no longer errors, needs no further change
// A statically-typed dictionary. How to reference a property type?
var things = { 'thing-1': 'baz', 'thing-2': 42 };
type Thing2Type = typeof things['thing-2'];
// ^ no longer errors, needs no further change
// A strongly-typed collection with special indexer syntax. How to reference the element type?
var nodes = document.getElementsByTagName('li');
type ItemType = typeof nodes.item(0);
// ^ the `.item` access works, but function applications still errors, would be fixed by either version of the proposal.
// A function returns a local/anonymous/inaccessible type, how can I reference this return type? (#4233, #6179, #6239)
// A factory function that returns an instance of a local class
function myAPIFactory($http: HttpSvc, id: number) {
class MyAPI {
constructor(http) {}
foo() {}
bar() {}
static id = id;
}
return new MyAPI($http);
}
declare function augmentAPI(api: typeof myAPIFactory(HttpSvc, number) /* ERROR */): any
// ^ function applications errors, would be fixed by either version of the proposal, if using slightly different syntax.
// I have an interface with a complex anonymous shape, how can I refer to the types of its properties and sub- properties ? (#4555, #4640)
// Declare an interface DRY-ly and without introducing extra type names
type MyInterface = {
prop1: {
big: {
complex: {
anonymous: { type: {} }
}
}
},
// prop2 shares some structure with prop1
prop2: MyInterface['prop1']['big']['complex'];
}
// ^ no longer errors after swapping `.k` access to `['k']`. `typeof` was unnecessary and counter-productive -- MyInterface isn't exposed on the expression level.
ìŽ ìì ë ë ìŽì ììŽë ì í ì ê·Œ ë°©ìì ëí ì¬ë¡ë¥Œ ë§ìŽ ë§ë€ì§ ìë ê² ê°ìµëë€. ëë¶ë¶ì 구ììŽë©° ì¬ìí êž°ë¥ ìì© íë¡ê·žëšì ë ì€ íëì ìíŽ íì±íë©ëë€.
ë¶ëª
í ì í ìì€ êž°ë° íšì ìì© íë¡ê·žëšì tinganho, TS í곌 ë ìì ìŽ typeof
륌 íµíŽ ííì ë³ì륌 ë
žì¶í ì ìì§ë§ ìžêžíë¯ìŽ ì í ìì€ì ííìì ë
žì¶ë êž°ë¥ë³Žë€ ë€ëšìŽì§ë 겜í¥ìŽ ììµëë€. ìì€. ìŽ íšì ìì© íë¡ê·žëš ì첎ì ê·íê° ìžêží íì° êµ¬ë¬žì ë¶ëª
í 죌ì ììŽë©°, ì ë ë¶ëª
í ìŽë¬í 묞ì ê° íŽê²°ëꞰ륌 ë°ëëë€. ìë§ë íì¬ ê²©ì°šì ëë¶ë¶ìŽ ì¬êž°ìì íŽê²°ë ìë ììµëë€.
ì ì¬íê², ííì ì°ì ì ê·Œ ë°©ìì <MyType> whatever
ëë whatever as MyType
륌 ì¬ì©íì¬ ì íì 죌ì
íë ê²ë íì©íì§ë§ ì í ì ê·Œ ë°©ììì typeof
ì²ëŒ ì ì¬íê² ì¬í ê³ ë €ì²ëŒ ë³ŽìŒ ê²ì
ëë€. ì í/ì ë€ëŠì ì ì¥ë íšì륌 ì ì©íë ë°©ë²ìŽ ëšì ììŒë©°, ìŽë íŽë¹ ì í êž°ë° ì ê·Œ ë°©ìì ì€ì ë¶ê°ê°ì¹ì ëë¶ë¶ì ì°šì§í ì ììµëë€(ê±°êž°ì ìžêžëì§ë ììì§ë§) -- ì í êž°ë° ì¡°ê±Žë¬žë¿ë§ ìëëŒ ê³ ì°š íšìì ëí ì íí ì¶ë¡ promised
ì€ë ëììì ê°ìŽ.* ë ëì ê²ì OPì ì¬ì© ì¬ë¡ì ë¬ëŠ¬ íŽê²° ë°©ë²ìŽ ììµëë€.
ììŽëìŽê° 충ëíë ìì¹ë¥Œ ì ì ìë€ê³ ìê°í©ëë€. íì¬ ì ììë typeof
í€ìëê° ííì ê°ì¹ ìì€ìŒë¡ ì ííëì§ ì¬ë¶ì $ typeof
륌 ê·žëë¡ ëë ê²ì ëíŽ (ëŽ íŽìì ë°ë¥Žë©Ž) 몚ìë 견íŽê° ììµëë€. , ê·žë¬ë ì í ìì€ìì íšì ìì© íë¡ê·žëš 구묞ì ë
žì¶í©ëë€.
ëŽê° 볎Ʞì ê·ž 몚ìì ë€ì ì°ì°ì ìŽë€. ëë ë ì¬ì© ì¬ë¡ì í©ë²ì±ì 묎ìíì§ ìì ê²ì ëë€. ë ë€ êµ¬íëë€ë©Ž ì믞 충ëì íŒíë ì¶ê° í€ìë륌 볌 ì ììµëë€. í€ìëê° ìŽë€ ììŒë¡ë ëë ì§ ì¬ë¶ë ìì§í 묎êŽì¬í©ëë€. ê·žë¥ ì묎ë ê²ë ì ë ¥íê³ ì¶ìµëë€.
*: ì ë€ëŠìì íŽë¹ ì íì 캡ì²íë ëì 맀ê°ë³ì ìŽëŠìŒë¡ 맀ê°ë³ìì íšì륌 ì°žì¡°íì¬ ê³ ì°š íšì륌 ì¬ì©í ì ìë€ë ê²ì ë°©êž ê¹šë¬ììµëë€.
ì€ì ë¡ ìë°©í¥ìŒë¡ ë³íí ì ìë ê²ì²ëŒ 볎ì
ëë€. typeof
ë ê°ì¹ ìì€ìì ì í ìì€ìŒë¡ ì¬ëŠ¬ë ë° ëììŽ ëë ë°ë©Ž declare let y: x;
ë ê°ì¹ ìì€ìì ì í ìì€ìŒë¡ 묌걎ì ì¬ëŠ¬ë ë° ëììŽ ë©ëë€. OPì íŽê²° ë°©ë²ì²ëŒ ì°ìíì§ ìì§ë§ ê·žë ìµëë€.
ì륌 ë€ìŽ ëª
ìì ì ë€ëŠì íµíŽ íšì ì íì ê°ì žìš 겜ì°ìë ìŽê²ìŽ ëììŽ ëì§ ìì ê²ìŽëŒê³ ìê°í©ëë€. ìŽ ì íì ìŽëí ë°©ë²ìŽ ìë ì í ìì€ì ìì ê²ì
ëë€.
ëŽê° ì ì ì ìŒë¡ êž°ë¥ êž°ë°ì ë€ë£šêž°ë¥Œ í¬ë§íë ê²ì²ëŒ ë€ëŠ¬ë©Ž ìë§ë íŽê²°ëì§ ìì ì
ë ¥ 묞ì ì ëí ëì ì§í ìí©ìŽ ìŽ íëì ì¶ê° êž°ë¥(5453ì ëíŽ ìžêžëš)ìì ì°šëšëìêž° ëë¬žìŒ ê²ì
ëë€. ê·žë¬ë ì°ëŠ¬ê° ìŽë¬í ê²ë€ì ììëŒ ì ìë€ë©Ž ê·žë§í ê°ì¹ê° ììµëë€.
ížì§: ì§êžì ííì êž°ë° ì ê·Œ ë°©ììì ì ìžë ì ìë ëª ê°ì§ ìŽë¡ ì ì¬ë¡ë¥Œ ìê°íŽ 볎ìì§ë§ ìì§ ì€ì§ì ìž ì¬ë¡ë ë ì€ë¥Žì§ ìììµëë€.
declare function f<G extends (...args: any[]) => R, R extends <T>(foo: T) => Bar<T>>(g: G): typeof R(baz); // error following the expression-based proposal: R is not exposed at the expression level
. G
맀ê°ë³ì ì íì ìê³ ì ê³µí ì ìë€ë©Ž ìŽë¬í ì 볎ë ë¬Œë¡ ê³ì°í ì ìì§ë§ ì§êžê¹ì§ ìŽ ì 볎륌 ì»ì ì ìë ë°©ë²ì ììµëë€(#14400?). ìŽ ë²ì£Œìë ììì ìžêží AngularJSìì ì¬ì©ëë í©í 늬 êž°ë¥ìì ìëíë êž°ë¥ìŽ í¬íšë ê²ìŽëŒê³ ê°ì í©ëë€.@Igorbek ìŽ ì€ ëí«ìŒë¡ êž°ëíë ê²ì ìŽíŽí ì ììµëë€.
function use<T>(item: typeof someFunctionWithComplexReturnTypeThatUsesGenerics<T>(item)) { ... }
ê·žê²ì ìí ì ìì²ëŒ 볎ì ëë€.
@masaeedu ì£ì¡í©ëë€.
( someFunctionWithComplexReturnTypeThatUsesGenerics
f
ë¡ ì í)
function use<T>(item: typeof f<T>(undefined as any as T)) { ... }
ììží ì€ëª íìë©Ž íì¬ë¡ìë ê°ì§ ë³ì륌 ëì íì¬ íŽê²°í ì ìë 묞ì ì ëë€.
const _typeofItem = f<T>(undefined as any as T); // no T here
function use<T>(item: typeof _typeofItem) { ... }
BTW, typeof
ì ì°ì ììê° ë ëêž° ë묞ì íì¬ ì ììŽ ë©€ë² ì í 쿌늬 ì í ì°ì°ì T[K]
ì 충ëíë€ë ê²ì ë°©êž ê¹šë¬ììµëë€.
typeof x[K]
ë íì¬ (typeof x)[K]
륌 ì믞í©ëë€. ì¬êž°ì K
ë _a ì íì
ëë€.typeof x[k]
ë (typeof x)[k]
$륌 ì믞í©ëë€. ì¬êž°ì k
ë ì íì
ëë€. ëëtypeof x[k]
ë typeof (x[k])
$륌 ì믞í©ëë€. ì¬êž°ì k
ë ííìì
ëë€.ì믞ì ëìŒíêž° ë묞ì ì€ì ë¡ typeof (x[k])
륌 ì ížíì§ë§ íì€í ë³ê²œ ì¬íì
ëë€.
Chromeì ê°ë°ì ë구륌 ì¬ì©íì ë íì ì°ì°ìì ì°ì ììê° ë ëë€ë ê²ì ìììµëë€. ìŽëì ì°ŸììŽ?
@Igorbek : ì, ìë ê²ì묌ì type Thing2Type = typeof things['thing-2'];
ê° ìŽë¯ž ìëíë ìŽì ìž ê² ê°ìµëë€.
@dehli : JS íí ìì€ì TS ì í ìì€ê³Œ ë¹êµíê³ ììµëë€. ëìŒíì§ ììµëë€. íëë ëžëŒì°ì /ë žëìì ì€íëê³ ë€ë¥ž íëë TS 컎íìŒë¬ìì ì€íë©ëë€.
ì ë ê°ìžì ìŒë¡ TypeScriptê° ìžë±ì±ë ì í ì¡ìžì€ë³Žë€ ë ëì ì°ì ììë¡ ì í ìì€ typeof
ì íŽê²°íë ê²ìŽ ìŽì íë€ê³ ìê°í©ëë€. ìì§í ë§íë©Ž ê±°ì ë²ê·žì²ëŒ 볎ì
ëë€. (ê·ž ìŒìŽì€ê° ì€ì ë¡ í
ì€ížê° ëìëì§ ê¶êží©ëë€.)
@tycho01 ê°ì± . TSë JSì ëìŒí ì°ì ìì륌 ì¬ì©íë€ê³ ê°ì íìµëë€.
@dehli íí ìì€ì ëìŒí©ëë€. ì í ìì€ìì ì ì¬í 구묞ì ê°ì§ ë ë€ë¥ž ê²ìŽì§ë§ 묞ììŽ ëì ì íì ë°íí©ëë€.
ì°ì ììë ê·žë€ìŽ ê°ì§ ê²ìŒë¡ ììíë ì íì ê²°ê³ŒìŒ ì ìë€ê³ ìê°í©ëë€. ê·ž êž°ë¥ìŽ íì¥ëìŽìŒ íë€ë©Ž ìŽë¬í ê³ ë € ì¬íìŽ ë ìŽì í©ëŠ¬ì ìŽì§ ìì ê²ì²ëŒ ë³ŽìŒ ì ììì ìžì í©ëë€.
ë ë€ë¥ž ì°žê³ ì¬íìŒë¡, ì ìì ë ë²ì ìŽ ëªšë 구íëìŽìŒ íë€ë©Ž êŽížë ì°ëŠ¬ê° ìŽì ëí ìì€ì ëª ìì ìŒë¡ ì ì§íë íšê³Œì ìž ë°©ë²ìŽ ë ê²ì ëë€. ëë ííì²ëŒ ë€ëŠ¬ì§ ìë ê²ë€ì ìê°íŽëŽë ë° ìŽë €ìì ê²ªê³ ììµëë€. íì§ë§ ê·žë ìµëë€.
@Igorbek ìŽê²ìŽ ììì ííììì typeof
ì ëí ëëšžì§ ì£Œì ì¬ì© ì¬ë¡ì
ëê¹? ì°ëŠ¬ê° #14400ì ì»ëë€ë©Ž, ëŽê° íëŠ¬ì§ ììë€ë©Ž ìŒë° ì¬ì©ì ì ì ì íì ì¬ì©íì¬ ì°ëŠ¬ìê² returnof
륌 ì€ ê²ì
ëë€.
returnof
륌 ì ê³µíì§ ììµëë€.type Return<T extends () => R, R = any> = R;
// overloaded function
declare function f(item: number): number;
declare function f(item: string): boolean;
type fType1 = Return<typeof f>; // ??
type fType2 = typeof f(1); // number
type fType3 = typeof f('a'); // boolean
// generic function
declare function g<T>(item: T): T;
type gType1 = Return<typeof g>; // ??
type gType2 = Return<typeof g<number>>; // not supported syntax
type gType3 = typeof g(1); // number
type gType4 = typeof g<number>(1); // number
type gType5 = typeof g('a' as 'a'); // 'a'
ëë ëëšžì§ ì¬ì© ì¬ë¡ë¥Œ 몚ë ìì§ ëª»íë©° ìì§ ë°ê²¬ëì§ ìì ê² ê°ì§ë§ ê°ì¥ íì ì¶ì¢ ì ë¶ííê³ ë§€ë ¥ì ìž ê²ì ë€ì곌 ê°ìµëë€.
typeof
ê° íì€ ê³Œë¶í íŽê²°ì ì¬ì©íêž° ë묞ì #12424ë¡ ì»ì ì ìë íšì¬ ë ê°ë ¥í _ì¡°ê±Žë¶ ë§€íë ì í_; @tycho01 ì promised
ì í PR #17077ìì ì°ìí ì륌 볎ì¬ì£Œììµëë€.@masaeedu : ì¢ì ì§ë¬žì ëë€. 짧ì ë²ì ì @Igorbek ìŽ ë§í ê²ê³Œ ê±°ì ê°ìµëë€. íŽê²°ë 구첎ì ìž ê³Œì ì ëí ììží ëŽì©ì ë³Žë €ë©Ž #16392ì 'íìí 죌ì êž°ë¥' 목ë¡ìì 짧ì 목ë¡ì ì°Ÿì ì ììµëë€.
ì¬êž°ìë ë€ììŽ í¬íšë©ëë€.
ReturnType
륌 ê°ìí ë êŽì°®ì ê²ì
ëë€.reduce
/ map
/ filter
/ find
-- ë°ë³µ ë° ê²ì¬ì êŽë šë 몚ë ê²ì ëí ì íí ë°í ì íì ê°ìêž° ê³ì°í ì ììµëë€. stdlib.d.ts
ë ê±°êž°ì ëììŽ ë ê²ìŽë©° Ramda/Lodashì ê°ì FP ëŒìŽëžë¬ëŠ¬ë ë§ì°¬ê°ì§ì
ëë€. ì€ì ë¡ ëªšë ì
ë ¥ìŽ ìë €ì§ ê²ì ìëì§ë§(ííë³Žë€ ëª©ë¡ê³Œ ì ì¬í ë°°ìŽìŽ ë ë§ì) ê°ì²Žì ëí map
ë° filter
ìì
ë Partial
ë³Žë€ ë ì ì
ë ¥ë ì ììµëë€. ìŽë redux(https://github.com/piotrwitek/react-redux-typescript/issues/1 ì°žì¡°) ë° Angularì ngrxì ê°ì ë ëì ì í ìí êŽëŠ¬ ëŒìŽëžë¬ëŠ¬ì íìí©ëë€. ì ì
ë ¥ë map
ì°ì° ììŽë DRY'er ì
ë ¥ ë°ìŽí°ì ì í ìì€ìì ìíë 결곌륌 ê³ì°í ë°©ë²ìŽ ìêž° ë묞ì
ëë€.flatMap
- promised
ì ì곌 ê°ì ìì
ì ëí ëí íŽì ì í0
ì ì륌 íì©íì§ ìëë€ê³ ë§íë ë° ëììŽ ë ì ììµëë€. 볞ì§ì ìŒë¡ #4183ì 죌ì ìž ì íìì 빌ë íŽí¹ì
ëë€. ëë ìì§ ëë¶ë¶ì ì¬ì© ì¬ë¡ë¥Œ ììíì§ ëª»íë€ê³ íì íì§ë§, function div<B extends number, NotZero = { (v: '1') => 'whatever'; }({ (v: 0) => '0'; (v: number) => '1'; }(B))>(a: number, b: B)
ì ê°ìŽ ìŽê²ìŒë¡ í ì ììµëë€. ìŒë°ì ìŒë¡ Idris ìžìŽë êžžìŽ ìì 벡í°/íë ¬ ì°ì°ìŒë¡ êŽê³ íì§ë§ ê³ ì°š íšììë§ íìí©ëë€.IsUnion
륌 ì¬ì©íì¬ ì
ë ¥ ì íì ëí Union<T>
/ NonUnion<T>
ì ìœ ì¡°ê±Žì íííë ë°©ë²ì
ëë€.curry
, Function.prototype.bind
, Promise.all
ì ê°ì íšì륌 ì
ë ¥íë ë°ìë ëììŽ ë©ëë€.switch
ë
ŒëŠ¬, ì¬êž°ì íšì ì€ë²ë¡ë íšíŽ ìŒì¹ë¥Œ íµíŽ íŽê²°ëšpromised
)ì 죌ì ìž ë§€íë ì¡°ê±Žë¶ ì íì
ëë€.Omit
, Overwrite
from #12215)곌 ê°ì ê°ì²Ž ì íìì 묞ììŽ ìžë±ì€ ì¡Žì¬ ì¬ë¶ íìž, #12424ì ëŽ ì€ëª
ì°žì¡°toString
, toLocaleString
)ì ìŽëŠê³Œ ìŒì¹íë 묞ììŽì íìžíëë¡ ê°ì²Ž ì í ìì± ì¡ìžì€ë¥Œ ìì íë ë°©ë²ì ëì 묞ììŽ ìžë±ì€ë¡ íìžë©ëë€. íë¡í íì
ë°©ë²ë³Žë€ ìŽì ì ê²°íšìŽ ìë ëŽì¥ ê°ì²Ž ìì± ì¡ìžì€ì ìì¡Žíë ë€ë¥ž 몚ë ì í ìì
ìì toString
ê°ì²Ž ì¡ìžì€ì êŽë šë ê²°íšì ì ì¬ì ìŒë¡ ìì í©ëë€.ížì§: ìì± ìì ë¶í° ì¡°ê±Žë¶ ì í(#21496)ìŒë¡ ì±ìì§ ì¬ì© ì¬ë¡ë¥Œ ì§ì ìµëë€.
@Igorbek ì íí ì°ì ì ê·Œ ë°©ì ì ìì (ì 목ë¡ì ìŒë¶ì ëí ìë €ì§ì§ ìì ìì© íë¡ê·žëšì 깚ë ëê°ë¡-- 구ìì ì¹ íŽì§ë ê²ìŽ ëë µì§ë§ ìì§ êµ¬ì²Žì ìž ê²ì ìê°íì§ ëª»íìµëë€. ) ì¶ê°ë¡ íì¬ ìŽ íšì ìì© íë¡ê·žëš(this #6606), spread/rest(#5453), ì£Œì¥ ì°ì°ì !
(#17370), ê³µì©ì²Ž ì í곌 ê°ì ê²ì í¬íšíë ê°ê³Œ ì í ìì€ ê°ì 격찚륌 ì¢í ê²ì ìœìí©ëë€. ì í ê°ë륌 íµí ëºì
(#4183, ê·žë ì§ ììŒë©Ž ììì ìžêží ì ìœ ì¡°ê±Žì íµíŽ ë¬ì± ê°ë¥), ê·žëŠ¬ê³ ìë§ë ë ìŽì ëŽ ëšžëŠ¬ êŒëêž°ìì ìê°í ì ììµëë€.
ìŽ ëªšë ì 충ììŽ ëìŒí êž°ë¥ì ë ê°ì§ ë°©ì(ì€ì ì í ìì€, ì í ìì€ì í¬íšë ì¡ìžì€ ì ìì€)ìŒë¡ ì¡ìžì€í ì ìëë¡ íë ìŽì ì ê°ì ëª ê°ì§ ì§ë¬žì ì êž°í ì ìë€ê³ ìê°í©ëë€.
ížì§: ì¶ê° ì ì¬ì 묞ì ë¡ ìì ë¹êµ ëêžì ì ë°ìŽížíìµëë€.
ížì§ 2:
ë¶íí ê²ì ì볞 ê²ìë¬ŒìŽ null &
íŽê²° ë°©ë² ììŽ ìŒë¶ ê·¹ëšì ìž ê²œì°ë§ ìì±í ì ìë€ê³ ë¯¿ê² íë€ë ê²ì
ëë€. ê·žë¬ë ì€ì ë¡ ìŽê²ì ì£Œë³ ì»ší
ì€ížì ëíŽ ìë €ì§ íŽê²° ë°©ë²ìŽ ìë íì¬ TS륌 볎ë¥íë ì€ìí êž°ë¥ì
ëë€. .
ìŽë ë³ëì .d.ts
íìŒë¡ ìì±ë TSì ìí¥ì 믞ì¹ë€ë ê²ì ì믞í©ëë€. ìŽë stdlib.d.ts
ë¿ë§ ìëëŒ ìë JS íë¡ì ížì ë³ëë¡ ìì±ë 몚ë DT ì
ë ¥ìë ì ì©ëë©° ê±°ì ë³ê²œëì§ ììµëë€. JS ëŒìŽëžë¬ëŠ¬ë Flowì ê°ì ëììë ìŽë € ìꞰ륌 ìí©ëë€.
(ìŽë .ts
íìŽíì íšì¬ ë ì¢ì§ ììµëë€. OPì 'íŽê²° ë°©ë²'ì ì¬ì©íë ì íì ííì ìì€ì ìí¥ì 믞ì¹ì§ ìê³ ë ëì ìì€ì ì¬ì¬ì© ê°ë¥í ì íìŒë¡ 구ì±íë ê²ê³Œ ê°ìŽ 맀ê°ë³ìíë ì ìêž° ë묞ì
ëë€.)
@tycho01 ëª©ë¡ ì£Œì ì ê°ì¬í©ëë€. ëŽê° ìííŽìŒ íë ë§í¬ê° ë§ìŽ ììµëë€. ëë ì íì ëí íšíŽ ìŒì¹ë ìíê³ #6606ì 묞ì ì ëí íë¥íê³ ì€ì©ì ìž ì룚ì ì ëë€. ê·žë¬ë ê°ê³Œ ì í ìì€ìì ì¬ë¬Œ ì¬ìŽì íŒëìŽ ìŠê°íë ê²ìŒë¡ 볎ìŽë©° #6606ì ìŽ ìììì ê°ì ëì§ ìì ê²ì ëë€.
ìŽ êž°ë¥ìŽ íìí ìŽì ë ë€ìì íŽë¹íë ì í ííìì 구ì±í ë°©ë²ìŽ ìêž° ë묞ì ëë€.
typeof K[L]
ìŽì ) 묞ììŽ ëŠ¬í°ëŽ ì íì í€ì íŽë¹íë ê°ì²Ž ì íì ìì± ì íê° ìì€ êµ¬ì±ê³Œ íì ìì€ ííì íšê» ì¬ì©íì§ ìê³ ììíê² íì ìì€ ííì 구ì±íë ê²ìŽ ì€ì ë¡ ê°ë¥ íŽìŒ íë€ê³ ìê°í©ëë€. (a: A) => B
ëë A | B
ì ê°ì ì íìŽ Func<A, B>
, Union<A, B>
ì ê°ì ê°ëší 맀ê°ë³ìíë ì íì ì€íìŽê³ 맀ê°ë³ìíë ì íì ì¡°ìíêž° ìí ìŒë° ëêµ¬ê° ììŒë©Ž ì¢ì ê²ì
ëë€. (HKT, Fundeps ëë ì í ê°ì¡± ë±).
걎ì ì±ì ëí 곌ëí ìŽì ì TypeScriptì 목í ì€ íëê° ìëëŒë ê²ì ìê³ ìì§ë§, ìŽì ë¶í¬ëª í ë°©ììŒë¡ íšê» ìíž ìì©íë ë§ì ì í ìì€ ê°ë ìŽ ììµëë€. ì íìŽ ë¬Žììžì§ì ëí ìŒì¢ ì íìíì ì íìŽ ë€ë¥ž ì í(íì ì í ì§ì , 구조 ë¶íŽ ë±)곌 ìíž ìì©íë ë°©ìì ëí êž°ê³ì ê·ì¹ì ê·ì íë ë°©ë²ì 뚌 êžžì ê° ê²ì ëë€.
ê° ìì€ êµ¬ì±ê³Œ íì ìì€ ííì íšê» ì¬ì©íì§ ìê³ ììíê² íì ìì€ ííì 구ì±íë ê²ìŽ ì€ì ë¡ ê°ë¥ íŽìŒ íë€ê³ ìê°í©ëë€.
ì€, ì, ì ë ê°ìžì ìŒë¡ ê°ì¹ ìì€ êµ¬ì±ì ì¬ì©íë €ë ìëê° ì í ìììµëë€. ìŽê²ìŽ ì ê° ìëíë ì ë¶ì ëë€. ë°žë¥ ë ë²šìŽ íììë€ë©Ž ë ìì ë ì¬êž° íí죌ì ì§ìì ììì ê²ìŽë€. :íŒ
ê°ê³Œ ì í ìì€ ì¬ìŽì 격찚ë ëë¶ë¶ ì¢íì§ ê²ìŒë¡ ììëë©°(TC39ê° TSë³Žë€ ë¹ ë¥Žê² ìŽëí©ëê¹?) afaikìë ìŽë¯ž ë°ìŽë ì í ìì€ ì ììŽ ììµëë€(ìŽì ê²ì묌 íëš ì°žì¡°).
ì ì¥, ëë ëë¶ë¶ì ì¬ì©ìì 겜íì ë²ìŽëë êž°ë¥ì ìë¹ ë¶ë¶ì ëí íìŽíì 구ì±íë€ë ê²ì ìê³ ììµëë€.
ëŽê° 볎ë ë°©ìì íì€ ëŒìŽëžë¬ëŠ¬ì FP ëŒìŽëžë¬ëŠ¬ê° ë묎 ì ì
ë ¥ëìŽ TS ì¬ì©ìê° ìŽë¥Œ ìì±íê³ ì¶ë¡ ìŽ ìëìŒë¡ ì²ëŠ¬ëëë¡ íë ê²ì
ëë€.
TSìë ì í ìì€ ì°ì°ìê° ëª ê°ë°ì ìì§ë§ ìŽë¥Œ ì¬ì©íì¬ ì€ì 묞ì 륌 íŽê²°íë ê²(죌ì ìë #12215ì Overwrite
/ Omit
ì
ëë€)ì ìŒë° ì¹ ê°ë°ììê² ë¡ìŒ 곌íì ì¡°êž ëª» 믞ì¹ë ê²ì²ëŒ ë³ŽìŒ ì ììµëë€. ì ì¥, ê·žê²ë ìµê·Œê¹ì§ ì°ëŠ¬ë¥Œ ë°ë €ê°ê³ , ê·žê²ë€ì ìì§ íë¡í íì
/ìžë±ì€/ì¬ë³Œ ìŠê±°ë ìëëë€.
(a: A) => B ëë A | Bë Func , Union 곌 ê°ì ê°ëší 맀ê°ë³ìí ì íì ì€íìŽììµëë€.
ë€ì§ìŽì 맀ê°ë³ìíë ì íì ë³ì¹/ì í ìì±ìë¡ ë§ë€ ì ììµëë€. Foo<Bar>
륌 ì¬ì©íë ì í ìì
ì ê²œì° íëª©ìŽ íëë¡ ëšìíëëì§ ì¬ë¶ë ì€ìíì§ ììµëë€. ì€ëª
ì ë§ëì§ ì¬ë¶ë§ íìží©ëë€.
ìŽê²ì stdlib.d.ts
ê° íë ìŒê³Œ ê±°ì ë¹ì·í©ëë€ -- foo[]
ê° ìì§ë§ Array<Foo>
ì€ëª
ì 충족íë¯ë¡ Array.prototype
íìŽí곌 íšê» ìëí©ëë€.
ì€ì ë¡ ëììŽëë ê²ì ìëëë€.
type Union2<A, B> = A | B;
type TuplizeA<Tpl extends Union2<any, any>, A, B> = [Tpl[0], Tpl[1]];
// ^ sorry, no way to access union members through e.g. [0]
// type a = TuplizeA<1 | 2>;
type TuplizeB<Tpl extends any | any> = [Tpl[0], Tpl[1]];
// ^ sorry, no way to access union members through e.g. [0]
// type b = TuplizeB<1 | 2>;
type TuplizeC<Tpl extends Union2<A, B>, A, B> = [A, B];
type c = TuplizeC<1 | 2>;
// ^ need 3 arguments, maybe fixable with #14400
type TuplizeD<Tpl extends A | B, A, B> = [A, B];
// ^ need 3 arguments, maybe fixable with #14400
type d = TuplizeD<1 | 2>;
ê·žëì ì, íŽê²°íì§ ëª»íì§ë§ kubeì #14400ìŽ ì€ì ë¡ ëììŽ ë ì ìë€ë ê²ì 깚ë¬ììµëë€. ê·žëŠ¬ê³ ì€ë ìŒì° ê±°êž°ìì ë¹ì ì 볎ììµëë€!
ì€ì ë¡ íšìì ëíŽìë ë§ì°¬ê°ì§ì
ëë€. ìŽë #14400ìŽ íšì ë°í ì íë¿ë§ ìëëŒ ë§€ê°ë³ì ì íë ìíí ì ììì ìêž°ììŒì€ëë€.
ìŽ ì ê·Œ ë°©ìì íì¬ ì€ë²ë¡ë륌 ì¬ì©íŽìŒ íë©° íì¥ëì§ ìêž° ë묞ì ë¶ííì§ë§ ê·žë ìµëë€. ë€ì ìŒë°ííêž° ìíŽ êž°ë³žì ìŒë¡ ìŽë¬í #6606 íšíŽ ìŒì¹ ì€ë²ë¡ë륌 ì¬ì©íì¬ ë€ìí ì íì ëí ì¬ë°ë¥ž ìµì
ì ížëŠ¬ê±°í©ëë€.
ìŽë¥Œ ì¬ì©íì¬ ìŒë°ì ìŒë¡ íí ì íìŒë¡ ë³íí ë€ì ëŽ ìŠë¶ ë°©ì ì ì¬ì©íì¬ ë°ë³µíì¬ ìŽë»ê²ë ìëí ì ìë€ê³ ê°ì í©ëë€.
ê³µì©ì²Žì ê²œì° íí ì íìŒë¡ ë³ííë ë ìì ë°©ë²ì ìíìµëë€. ê·žë¬ë ììì ìì륌 ì¶ê°íê³ ìì 구묞/í€ìëë ìê°í ì ììµëë€.
ížì§: íŽë¹ ííì/ì í ìì€ êž°ë¥ ê²©ì°šë¥Œ ë€ì íìžíë €ë©Ž ë€ìì ìíí©ëë€.
!
(#17370): #6606 ìŽíì íŽê²° ë©ëë€.!
ì ìŒë°ì ìž ê²œì°ìŽë©°, ìŽ #6606ë ì ìœ ì¡°ê±Ž(ì: ìì NotZero
)ì íµíŽ ë¬ì±í ì ììµëë€.ArrayLike
List
í ì ììµëë€. ìŽ #6606ì ì¬ì©íì¬ ìŽì ì ì©ëì§ ìì íšììì 맀ê°ë³ì륌 ì¶ì¶í ì ìë€ê³ ìê°í©ëë€. ì ì© ìì ì 맀ê°ë³ì륌 ì¶ì¶íë 겜ì°(ìŠ, ì íí ì
ë ¥ ê°ì ì»êž° ìíŽ) ì¬ì í 5453ìŽ íìí©ëë€.ì컚ë, ìŽ ì ììŽ ì€íëë€ë©Ž ííì곌 ì í ìì€ ì¬ìŽì êž°ë¥ì ê²©ì°šê° ì¬êž°ì íí ì§í¥ì ìž ì ìì ëíŽ ê·žë€ì§ í° ë Œìì ìŒìŒí€ì§ ìì ê²ìŽëŒê³ ë§íê³ ì¶ìµëë€. 5453ë ììë€ë©Ž ë ìŽì ê±°êž°ì ëíŽ ìê°í ì ìììµëë€. ê·žëŠ¬ê³ ë묞 ììžì ê²œì° ìë ê²ì묌ì ìžêžë íŽê²° ë°©ë²ì ì¬ì í ââì íší©ëë€.
ìŽì ì¬ì í ìœê² ë§ë€ ì ìë 죌ì¥ì ííì êž°ë° ë³íì ì¬ì©íë©Ž ì í ìì€ìŽ 믞ë¬ë§ ì°ì°ì륌 ë°ëŒì¡êž° ì ìë ìŽ êž°ë¥ìŽ JS ì ëìŒí 구묞 ìŒë¡ ë žì¶ëë€ë ê²ì ëë€(íŽê²° ë°©ë² ìì). íìµ ê³¡ì ì ì€ì ëë€.
ížì§ 2:
ì íì ííì ìì€ìŒë¡ ê°ì žì€ë ííì ì ìì ížëŠ 1 as any as MyType
ìŽ íšì ì첎ììë ë
ŒëŠ¬ì ìŒë¡ ìëíŽìŒ íë€ë ê²ì ë°©êž ê¹šë¬ììµëë€.
ìŽê²ì ìë§ë ë ê°ì§ ë²ì ì ìíŽ íì±íë ì€ì êž°ë¥ìŽ ë€ì ì ì¬íŽ 볎ìžë€ë ê²ì ì믞í©ëë€. ìžì ìž ì°šìŽì ì ëë¶ë¶ typeof myVar
(ì í ë²ì ) ë myVar
(ííì ë²ì )ë¡ êµ¬ì±ëìŽ íšì ìì© íë¡ê·žëšìì ë³ì륌 ì¬ì©íë ê²ì
ëë€. MyType
(ì í í믞) ë 1 as any as MyType
(ííì í믞, ëì declare let a: any;
ë€ì <MyType>a
)ìì ì íì ì¬ì©í©ëë€.
ë ì€ íëì AST ë³ê²œ ì¬íë ꜀ êŽëŠ¬íêž° ì¬ìŽ ê² ê°ìµëë€. ííì í믞ë ëì ê° ííìì ê°ëŠ¬í€êž° ìíŽ typeof
ê²°í©ìŽ íìí©ëë€. type flavorë êž°ì¡Ž íšì ìì© íë¡ê·žëš 구묞( fn<T>(arg)
)ì ííììì ì í ìì€ìŒë¡ ë³µì¬íì¬ ìì RyanìŽ ì ìí ëë¡ êž°ì¡Ž 구íì ì°ê²°í©ëë€.
ê·žë¬ë©Ž ë€ì곌 ê°ìŽ ê·ê²°ëë€ê³ ìê°í©ëë€.
íí í믞ì 겜ì°:
typeof expr
TS ì í ìì€ ì§ì ìŽì ì íŽê²° ë°©ë²ìŽ ìë JS 구묞 í¬íšì í í믞ì 겜ì°:
MyType
ëì 1 as any as MyType
: ííì ë 벚ì ì í ë 벚ì ííì ë 벚ì ì í ë ë²šìŽ ììµëë€.ì§êžê¹ì§ 걎ëëŠ¬ì§ ìì êŽë š 죌ì ì€ íëë ìŽ ì í ìì€ íšì 'ìì© íë¡ê·žëš'ìì this
ë°ìžë©ì ì ê³µíë ë°©ë²ìŽììµëë€. ìŽì JS ëžëŠ¬ê²ìŽížë ìŽê²ì Function.prototype
ë©ìëì ë®ìŽì°ì§ë§, ê·žëë¡ë ì í ìì€ìì ìŽë¥Œ ì²ëŠ¬í ë°©ë²ìŽ ììµëë€.
ììì ìì 구묞, F
(this: Foo, a: number, b: string) => SomeReturnType
íšì ì íìŽ ì£ŒìŽì§ë©Ž F(MyA, MyB)
: F(this: MyFoo, MyA, MyB)
ë¡ ížì¶ë ì ììµëë€.
this
ë°ìžë©ì ë®ìŽì°ì§ ìê³ ë°í ì íì ê³ì°íë ê²ì ì¬ì í F(MyA, MyB)
ì ê°ìŒë©°, ë€ì ìì¹ìì ìŽë¬í íšì륌 ì¬ì©íë €ê³ íë©Ž ì í ìì€ this
ìžìê° ìŒë°ì ìŒë¡ 묎ìëë ë°©ìì 믞ë¬ë§í©ëë€. íí ìì€.
ìŽ ìì 구묞ì ì¥ì :
ìŽ ìì 구묞ì ëšì :
ì, ìŽê²ì ìŽë¯ž ìžìŽë¡ ëìŽ ììµëë€!
ë묎 í¥ë¶íì§ ë§ììì€.
@DanielRosenwasser ë ì í ëì 늬í°ëŽì ëí íšì ížì¶ì ì¬ì©í ì ìëë¡ íë ë²ê·žìž #12146ì ì§ì íìµëë€.
_5ë¶ í_
íë€! ì°ëŠ¬ê° íë¡ëì ìì ì ë ì¬ì©íŽìë ì ëë ëì°í ì¬ì í ê²ì ëë€. íì§ë§ ì í¹ì ìŽë€...
interface String {
passthrough<T>(v: T): T;
}
// All work
type ANumber = "".passthrough(10 * 10);
type AString = "".passthrough("hello" + "world");
type AHelloWorld = "".passthrough("hello world");
type AnArbitraryThing = "".passthrough(Object.assign({hello: "world"}, {foo: "bar"}));
type ThisCraziness = "".passthrough((() => "cows are big dogs"));
~ê·žëì ìŽ ë¬žì ì ëí Effort: Difficult
ê° ìœê° ìì¬ì€ë¬ì 볎ì
ëë€. ë§ì¹ ê·žë€ìŽ ê±°êž°ìì ì°ì°í ê·žë ê² í ê² ê°ìµëë€.~ ë ìœê³ ìŽëŠ¬ìê² ë껎ì§ëë€. ìŽê²ì ë©ì§ê² íêž°ê° _ ìŽë µìµëë€.
ìŠê±°ìŽ ìê° ë³ŽëŽìžì @tycho01.
@TheOtherSamP TypeScript 2.4.2ìì ìŽê²ì ìëíê³ ìŽë¬í 몚ë ì íì any
ìž ê²ìŒë¡ ì ì¶ë©ëë€.
@pelotom Huh, 2.4.2 ë° 2.5.0-dev.20170803ìì ìëí©ëë€. ëì es6 ë° ì격 몚ë.
ê·žë€ìŽ ë°©êž ê³ ì¹ ê² ê°ì§ë§ ëŽ ìëª»ìŽ ìëê¹ ê±±ì ë©ëë€. #17628
@TheOtherSamP ìëì, 죌ì¬ìê° ììµëë€. ì€ êžì.
@pelotom ìŽìíë€ì. ìì í ìë¡ìŽ íë¡ì ížìì ìëíê³ ììµëë€. ì€ì ìŽ ìŽë»ê² ë€ë¥žì§ ëªšë¥Žê² ìµëë€.
@TheOtherSamP : íí, ꜀ ìêž°ë€ì.
ìê°ì ìŒë¡ 볎멎 ê·žë€ìŽ ë¹ì ì ìœë©ížë³Žë€ ì¡°êž ì ì ìì ì ììí ê²ì²ëŒ 볎ì
ëë€. ì€ êžì.
@í ë¡í° :
TypeScript 2.4.2ìì ìŽê²ì ìëíê³ ìŽë¬í 몚ë ì íìŽ anyë¡ ì ì¶ëììµëë€.
ê·žì ì€ëí«ì Playground(2.3.2)ìì ìëíë ê² ê°ìµëë€. ê·žê² ìžë¶ì ìµì ë²ì ( ^2.5.0-dev.20170626
)ììë ì¬ìì°íë ë° ë¬žì ê° ììµëë€.
ê·žëì ìŽ ë¬žì ì ëí
Effort: Difficult
ê° ìœê° 몚ížíŽ 볎ì ëë€. ë§ì¹ ê·žë€ìŽ ê±°êž°ì ì°ì°í í ê²ì²ëŒ 볎ì ëë€.
ê·žë€ì ì í êž°ë° êµ¬íì ì°žì¡°íëë° ìŽë ìŒë¶ ë³ê²œì ì믞íë ë°ë©Ž ííì ìžìŽ(-> +
, Object.assign
, ì¶ê° íšì ížì¶)륌 ì¬ì©íë ê²ìŒë¡ 볎ì
ëë€.
@tycho01 #17618ìì êŽì¬ì ëë©Žì 몚ë ê²ìŽ _ìê°_í©ëë€. êžì, ê·žê²ì ë륌 íë¡ëì ìì ì¬ì©íë ê²ì ì§ì§íê² ê³ ë €íë ë²ì ê°ë¥Žì³ ì€ ê²ì ëë€.
ê·žë€ì ì í êž°ë° êµ¬íì ìžêžíëë° ìŽë ìŒë¶ ë³ê²œì ì믞íë ë°ë©Ž ííì ìžìŽ(-> +, Object.assign, ì¶ê° íšì ížì¶)륌 ì¬ì©íë ê²ìŒë¡ 볎ì ëë€.
ë€, ì ë ë°ë³Žìê³ ê·ž ë§ì í ëê¹ì§ ìŽ ì 첎 묞ì 륌 ìœì§ ìììµëë€. ê·žê²ì ìë§ë êž°ë¥ì ë ëì ë²ì ìŒ ê²ì ëë€. ê·žë¬ë ì°ëŠ¬ê° ì§êž ê·žê²ì ê°ì§ ì ìꞰ륌 ë°ëëë€. ëë íì ìì€í ì íê³ë¥Œ ë§ìŽ ë°ìŽ ëìê³ , ìŽê²ìŽë #12424ë ë§ì ì íì§ë¥Œ ìŽìŽì€ ê²ìŽë€.
#17961ìì PRì ìŽììµëë€.
@yortus ìŽê²ì 'typeof literal'ì 겜ì°ë¥Œ 컀ë²í©ëê¹?
ì€ëë TypeScriptë "const x: typeof 1 = 1;"ì ì°ë ê²ì íì©íì§ ììµëë€.
@NN--- ìë ì ìì 몚ë ííìì ë€ë£šì§ë§ 'ì¹ìžë' ë¶ë¶ì ìì± ì¡ìžì€ ë° íšì ë°í ì íë§ ë€ë£¹ëë€.
typeof 1
ê° íì©ëëëŒë 늬í°ëŽ ì í( 1
) ëë ë ëì ì í( number
)ì ì ê³µí ì§ íì í ì ììµëë€.
ì€ëë TypeScriptë "const x: typeof 1 = 1;"ì ì°ë ê²ì íì©íì§ ììµëë€.
ì const x: 1 = 1;
ê° ìëê°ì?
@SaschaNaz ëë ë€ì곌 ê°ì ê²ì ì°ê³ ì¶ììµëë€.
const a = {q:1};
const b = {q:1};
const x: ReadonlyArray<typeof a> = [a,b];
ê·žë¬ë 늬í°ëŽììë ìŽì ì ì¬íê² ìëíì§ ììµëë€.
const x: ReadonlyArray<typeof 1> = [1,2,3];
@yortus ì íí ì íì ëí ì¢ì ì§ì . 늬í°ëŽ ì íì ëíŽ ìê°íì§ ìììµëë€.
@NN---: ê·íì ìê° ìŽë¯ž íšê³Œê° ìë€ê³ ìê°í©ëë€.
@tycho01 íëŠìë ìŽì íšìì ë°í ì íì ê°ì žì€ë $Call
ì íìŽ ììµëë€. https://github.com/facebook/flow/commit/ac7d9ac68acc555973d495f0a3f1f97758eeedb4
typeof fn(...)
ë§ íì©íë ê²ì ììì ííìì typeof
륌 íì©íë ê²ê³Œ ëìŒíì§ ììµëê¹?
function fn() {
return /** whatever expression you like */;
}
type a = typeof fn();
ì íì íì íë ê² ìžì ë€ë¥ž 목ì ìŒë¡ ë°íì íšì륌 ë§ë€ê³ ìë€ë ì ì ì ìžíê³ ë?
ì€ë§. ííìì ì€íìŽ ìëëŒ ííìì ì í íê°ë¥Œ ìííê³ ììµëë€.
@dyst5422 typeof fn()
ë ì€ì ë¡ ííìì íê°íì§ ìê³ ëŠ¬íŽ ì íë§ ì ê³µí©ëë€.
ížì§: ìë§ë ê·žê²ìŽ ë¹ì ìŽ ë§íë €ê³ íë ê²ìŒ ìë ììµëë€. íì€íì§ ììµëë€. íì§ë§ @sky87 ìŽ _íê°_ê° ìëëŒ íì ííììì ì¬ì©íë ê² ìžìë ì묎 목ì ììŽ íšì _ì ì_ì ëíŽ ìŽìŒêž°í ê² ê°ìµëë€.
@dyst5422 , @pelotom ìŽ ë§íë¯ìŽ, ëë ë¹ì ìŽ ê·ž êž°ë¥ì ì€ííë€ë ê²ì ì믞íì§ ìììµëë€. ë ììží ì€ëª
íìë©Ž, ììì ííìì typeof
륌 íì©íì§ ìê³ íšìì ë°í ì íì typeof
륌 íì©íë©Ž ë ë³µì¡í ì íì íì
íêž° ìíŽ ë¬Žìì í ê²ì
ëê¹? ííìì ë°í ì íì ìì²í ì ìëë¡ íšìë¡ ëííë ê²ì
ëë€. ê·žê²ì ë°í ì íì ì»êž° ìíŽ ë°íìì íšì륌 ìì±íê³ ìì±íêž°ì ë ë§ì ìì©êµ¬ì
ëë€.
ížì§: ì€ì ë¡ ììì ííì ì íì ìŽë¯ž íì í ì ììµëë€. ìŽê²ì ì¶ì íì§ë§ ìëí©ëë€.
const dummy = (false as true) && /* arbitrary exp */;
type TypeOfExp = typeof dummy;
ìì§í ìŽë€ íŽí¹ì ì íží ì§ ëªšë¥Žê² ìµëë€. typeof
륌 ì¬ì©íì¬ ì§ì ì íì ìì²í ì ìë ê²ìŽ ê°ì¥ ì¢ì ë°©ë²ìŽëŒê³ ìê°í©ëë€.
ì, ì§êž íë¡ì°íê³ ììµëë€. ë€, ë€ì곌 ê°ìŽ ì¬ì©í ì ìë ê²ìŽ ë°ëì§í ë°©ë²ìŽëŒê³ ìê°í©ëë€.
type TypeOfExp = typeof (
false &
"false" &
0
)
ííì ì í íê°ë¥Œ ììë¡ ìíí ì ìëë¡
new
ížì¶ì ë°í ì íì 쿌늬í ì ììµëê¹? ëŽ ì¬ì© ì¬ë¡: PromiseConstructorLike
구í(ì: $q ëë Bluebird)ì ëí 찞조륌 íì©íê³ íŽë¹ 구íì ìíŽ ìì±ë Promise륌 ë°ííë íšìì ëí ì í 죌ìì ìì±íê³ ì¶ìµëë€.
declare function wait<P extends PromiseConstructorLike>(time: number, implementation: P): typeof new implementation<void>((res: any, rej: any) => void);
const bluebirdPromise = wait(1e3, Bluebird);
// typeof bluebirdPromise should be instance of Bluebird
typeof
ììŽ ë°í ì íì 쿌늬í ì ììµëê¹? ìëë©Ž null as FnType
íŽìŒ í©ëê¹?
interface Fn {
(a: string): string;
(a: number): boolean;
}
type Ret = Fn(number); // Ret = boolean
type Ret = typeof (null as Fn)(number);
ìŽ ì§ë¬žì ìŽë¯ž ëµë³ìŽ ëìë€ë©Ž ì£ì¡í©ëë€. ëë ê·žë€ì ì°Ÿì ì ììµëë€.
ì¬êž°ì new
ì ìì ì 묎ìì
ëê¹? ê·žë¥ typeof implementation()
륌 ìíì§ ììµëê¹?
ìëì, implementation()
ë ì íší ížì¶ìŽ ìëêž° ë묞ì
ëë€. PromiseConstructorLike
ë íŽë¹ ì í ì ìžì ë°ëŒ new
륌 íµíŽìë§ ížì¶í ì ììµëë€. typeof implementation()
ë (typeof implementation)['foobar']
ê° ì í ì€ë¥ìž ê²ì²ëŒ ì í ì€ë¥ì
ëë€.
FlowType곌 ê°ì ì¶ë¡ ê°ë¥í ì ë€ëŠ ì íì ëì í ì ììµëê¹? ì ìŽë íšìì ë°í ê° ì íì ê°ì žì€ë 묞ì ë íŽê²°í ì ììµëë€.
type _ExtractReturn<B, F: (...args: any[]) => B> = B;
type ExtractReturn<F> = _ExtractReturn<*, F>;
@Cryrivers : íŽë¹ ì ê·Œ ë°©ìì #14400ì ì°žì¡°íìžì. ì¶ë ¥ ì íìŽ ì ë ¥ì ë°ëŒ ë¬ëŒì§ë 묞ì ë ì€ì ë¡ íŽê²°ëì§ ììµëë€.
íšìì ëí ížì¶ìŽ ëì ìŒë¡ ë°ííë ê²ì ììíêž° ìíŽ ì€ë ë€ì ìŽê²ìŽ íìíê² ëììµëë€.
ReturnType<T>
ì°ì°ìë TS 2.8ì lib.d.ts
ì ì¶ê° ëë©° ì¡°ê±Žë¶ ì íìŒë¡ 구ëë©ëë€.
ReturnType<T>
ë ìì§ ìžì ì íì ë°ë¥ž ë°í ì íì ê³ ë €íì§ ììêž° ë묞ì ì°žê³ ë¡ ì¬êž°ì Flowì $Call
ì í 구íìŽ ììµëë€.
ížì§: ì£ì¡í©ëë€ @goodmind , ë¹ì ìŽ ìŽë¯ž ì íí ê·žê²ì ì°ê²°ëìŽ ìë€ë ê²ì 깚ë«ì§ 못íìµëë€.
ìµê·Œ TS ì¶ê° ì¬íì êž°ë°ìŒë¡ ìŽ ì ì(ëë íŽë¹ ì í ížì¶ íŽì)ì ì¬ì© ì¬ë¡ì ëí ìŽì ê²ì묌 ì ì
ë°ìŽížíìµëë€.
íšíŽ ìŒì¹ ì¬ì© ì¬ë¡ë ìŽì #21496ì ìíŽ ë€ë£šìŽì§ë©°, ... ì¬ì©ìê° ì ê³µí ëë€ë¥Œ êž°ë°ìŒë¡ ì íì ê³ì°íë €ë 겜ì°(ì: curry
, íšì 구ì±, map
, reduce
)
PS @thorn0 : ìŽì Angular ì¬ì© ì¬ë¡ë¥Œ ReturnType
(#21496)ë¡ ì±ìž ì ìë€ê³ ìê°í©ëë€!
ìŽ ííì íì©íšìŒë¡ìš ìŽê²ì 컀ë²íŽìŒ íë€ê³ ìê°í©ëë€.
prop2: this.prop1.big.complexì ì í;
@mhegazy ìŽê²ì ì¶ì íêž° ìí ë³ëì 묞ì ê° ììµëê¹?
typeofê° ë¡ì»¬ììë ìëíì§ë§ ìì±ììë ìëíì§ ìë ë°ë©Ž ì ì ìì±ììë ìëíë ê²ìŽ ì§ìŠë©ëë€.
class A {
x: number;
static y: number;
f() {
const a: number = 1;
const b: typeof a = 2; // OK
const c: this.x = 3; // No :(
const d: this['x'] = 3; // OK
const e: typeof A.y = 4 // OK
}
}
@NN--- íì ìžë±ì±ë ì íì ì¬ì©í ì ììµëë€.
this['x']
@cameron-martin ìëíì§ ììµëë€. ìŽëì¥
@tycho01 ìë¡ìŽ ì íì ì¶ë¡ 곌 조걎ì íë¥íì§ë§ íšì ì€ë²ë¡ë©ì ìëíì§ ìëë€ë ì ìì ë§€ì° ì§ìŠì€ëœìµëë€. 죌ìŽì§ ìŽì ë ê°ë¥í ê² ì€ìì íšì ì íì íŽê²°íêž° ìíŽ ìŽì ê°ì typeof
ê° íìíêž° ë묞ì
ëë€.
@NN ì const d: this['x'] = 3;
륌 ì¬ì©íìžì.
ì€, ì¢ìì :)
@NN--- ëë ì¬ì©
class A {
x: number;
static y: number;
f() {
const self = this;
const a: number = 1;
const b: typeof a = 2; // OK
const c: typeof self.x = 3; // OK
const d: typeof self['x'] = 3; // OK
const e: typeof A.y = 4 // OK
}
}
@tofist ë¡ì»¬ìŽ ìëíë€ë ê²ì ìê³ ìì§ë§ ìŽê²ì ì¶ì
í©ëë€.
ììì 캡ì²ë¡ ëë€ë¥Œ ì¬ì©íë ëì 'function(){}' ìœë°±ì ëíŽ 'this'륌 ìëìŒë¡ ì ì¥íë ê²ê³Œ ê°ìµëë€.
@NN
ìŽ ëª»ìꞎ.
ë€, ìŽê²ì ëšì§ ìµì ì ëë€ :)
í¹ì ìžì ì§í©ì ì íšì±ì ê²ì¬íë €ë ê²œì° í¹ì ë€ë¥ž ë³ì¹ê³Œ íšê» ReturnTypeOf<T>
륌 ìì±í ì ììŒë¯ë¡ ì¡°ê±Žë¶ ì íì ìŽì ìŽê²ì í¬ê² êŽë šìŽ ìê² ë§ëëë€. ê·žë€ì 곌ë¶í íŽê²°ì í ì ìì§ë§ ì°ëŠ¬ë ìŽ êž°ë¥ìŽ ê·ž ì¬ì© ì¬ë¡ì ëí ë³µì¡ì±ë§íŒ ê°ì¹ê° ìë€ê³ ìê°íì§ ììµëë€.
@RyanCavanaugh ReturnType<T>
ë§ìíìë ê² ê°ìë°ì?
@RyanCavanaugh ë¶íí ìŒì ëë€. 곌ë¶í íŽê²°ìŽ ì ê° ì ë§ íìíë ê²ì ëë€. 조걎ë¶/ì¶ë¡ ì íì 곌ë¶í íŽê²°ì ì¶ê°íë ê²ì ì¶ì íë ë ë€ë¥ž 묞ì ê° ììµëê¹?
ë€ì곌 ê°ìŽ ìì±í ì ììŽìŒ í©ëë€.
type Return1<A1, T extends (a: A1) => any> = T extends (a: A1) => infer R ? R : any;
type Return2<A1, A2, T extends (a: A1, a: A2) => any> = T extends (a: A1, a: A2) => infer R ? R : any;
declare function something(a: number): number;
declare function something(a: string): string;
declare function something(a: number, b: string): boolean;
type A = Return1<number, something>; // number
type B = Return1<string, something>; // string
type C = Return2<number, string, something>; // boolean
ëë ê·žê²ì í ì€ížíì§ ìììŒë©° ê° ìžì ìì ëíŽ ë³ëì ëì°ë¯žê° íìí©ëë€.
@ForbesLindesay : something
ë íì¬ ííì ìì€ ë³ìì
ëë€. ì륌 ë€ìŽ ì¬êž°ìì typeof
ë¡ ì°žì¡°íê±°ë ìží°íìŽì€ë¡ ì ìžíë©Ž ìì ë©ëë€. ëë ì€ì ë¡ ì ì í ë°í ì íì ì°ì¶íëë¡ êŽëŠ¬íê³ ìì§ ììµëë€( 2.8.0-dev.20180318
).
@ForbesLindesay ë¶ííë ëë ê·žê²ìŽ íšê³Œê° ìë€ê³ ë¯¿ì§ ììµëë€. ì¶ë¡ ë©ì»€ëìŠì _last_ ë©ìë ì€ë²ë¡ë륌 ì íí©ëë€.
type Funcs = ((p1: string, p2: string) => void) & ((p1: number) => void);
type FuncPromise1<T> = T extends (p1: infer P1) => void ? (p1: P1) => Promise<[P1]> : never;
type FuncPromise2<T> = T extends (p1: infer P1, p2: infer P2) => void ? (p1: P1, p2: P2) => Promise<[P1, P2]> : never;
let foo: FuncPromise1<Funcs> & FuncPromise2<Funcs>;
ê·žë¬ë ì¶ë¡ ë©ì»€ëìŠì íí íµí©ì _is_ ì²ëŠ¬í ì ììµëë€.
type Tuples = [string, string] | [number];
type TuplePromise1<T> = T extends [infer P1] ? (p1: P1) => Promise<[P1]> : never;
type TuplePromise2<T> = T extends [infer P1, infer P2] ? (p1: P1, p2: P2) => Promise<[P1, P2]> : never;
let foo: TuplePromise1<Tuples> & TuplePromise2<Tuples>;
ì€ë²ë¡ë -> ê°ì²Ž, íšì -> ê°ì²Ž, ëí íŽì 륌 íì©íë ê²ìŽ íìí ì ììµëë€. ê±°êž°ìì ì í 맀í ë° ì¶ë¡ ì ìíí ë€ì íšì ë° ì€ë²ë¡ëë¡ ë€ì ëíí©ëë€.
@MeirionHughes :
ì€ë²ë¡ë -> ê°ì²Ž, íšì -> ê°ì²Ž, ëí íŽì 륌 íì©íë ê²ìŽ íìí ì ììµëë€. ê±°êž°ìì ì í 맀í ë° ì¶ë¡ ì ìíí ë€ì íšì ë° ì€ë²ë¡ëë¡ ë€ì ëíí©ëë€.
(a: number, b?: string) => boolean
-> { a: number, b?: string }
? ì°ëŠ¬ë ìì§ ê·žë° ë§€ê°ë³ì ìŽëŠì ì»ì ì ìì§ë§ ê°ë
ì ìŒë¡ ìŽê²ì ëëšžì§ ë§€ê°ë³ì( (a: number, ...b: string[]) => boolean
)ì ëíŽ ë ìŽë €ìì§ëë€. ëí ê°ì²Ž ì íì ì¬ì©íì¬ ìì륌 ì§ì í ì ìêž° ë묞ì
ëë€.
ììë ìë§ë ìŽëŠë³Žë€ ë ì€ìíë©° 맀ê°ë³ìì íí ê°ì ë³íí ì ììµëë€ . ì€íë ë/ìµì ì ì¬ì í ââìœê° ë³µì¡í ì ììµëë€.
ìŽê²ì 곌ë¶í륌 ì¶ì¶íë 묞ì 륌 ì€ì
ëë€. ì€ë²ë¡ëë ((a: number) => 123) & ((s: string) => 'hi')
ì ê°ì íšì ì íì êµì°šì¬ìŒ í©ëë€. ë°ëŒì 묞ì ë êµì°š ì í(ì: íí ì íìŒë¡)ì 'í¬ì¥ íŽì 'íë ë°©ë²ì
ëë€. íì¬ë¡ìë ê·žë° ê²ìŽ ììµëë€.
곌ë¶í ì ì€ ìŒìŽì€ë¥Œ ë€ë£šì§ë§ ì ë€ëŠì ë§íì§ ìêž° ë묞ì ìŽ ê²œë¡ê° ë¶ë§ì¡±ì€ëœë€ë ê²ì ìììµëë€. íì§ë§ ê·žë ìµëë€. êµì°šë¡ íêž° ìì ì ì¬ì í ââââìŽë 쪜ìŽë ê°ìŽììµëë€.
ìŽì ìŽ ë¬žì ê° ì¢ ë£ëììŒë¯ë¡ ìì§ ëëœë ë¶íì ëí ìë¡ìŽ ì ììŽ ììµëê¹? ìžìì ë°ëŒ ë°í ì íì ì²ëŠ¬íë ë°©ë²ê³Œ ê°ì?
ìŽì ìŽ ë¬žì ê° ì¢ ë£ëììŒë¯ë¡ ìì§ ëëœë ë¶íì ëí ìë¡ìŽ ì ììŽ ììµëê¹?
ëŽê° ìê³ ìë ê²ì ììµëë€.
ìžìì ë°ëŒ ë°í ì íì ì²ëŠ¬íë ë°©ë²ê³Œ ê°ì?
íµí ì íì ì¶ì íë ë° ë¬žì ê° ìë€ê³ ìê°íì§ ììµëë€.
ì í ìì€ êž°ë¥ ìì© íë¡ê·žëšì ì¶ê°íë ììŽëìŽì ëí ìë¹ ì§ììŽ ììµëê¹? ëë ê·žê²ì ëí ì ìì ìì±í ì ììµëë€. 묞ë²ì ìŒë¡ë ê·žê² ê°ì¥ ì¬ìŽ êžžìŽëŒê³ ìê°í©ëë€.
type MyType<A> = {
foo: A
}
type Wrap = {
<T>(maybe: MyType<T>): MyType<T>;
(maybe: any): MyType<any>;
}
type Naive = ReturnType<Wrap>; // Naive = { foo: any }
type Proposed1 = Wrap(maybe: number); // Proposed1 = { foo: number }
type Proposed2 = Wrap(maybe: MyType<number>); // Proposed2 = { foo: number }
type Proposed3 = (<T>(maybe: T) => MyType<T>)(maybe: number) // Proposed3 = { foo: number }
ì£ì§ ìŒìŽì€:
const foo = <T>(a: T) => T:
type Edge1 = (typeof foo)(a: number) // Probably trivial?
type Foo = {
<T>(a: string): T
}
type Edge2 = Foo<number>(a: string) // Should this be allowed? Probably not, because:
type Bar<A> = {
(a: string): A
}
type Edge3 = Bar<number>(a: string) // Things are getting strange
interface Baz<A> {
<T>(a: T): T | A
}
type Edge4 = Baz<number>(a: string) // What is this?
ì í ìì€ êž°ë¥ ìì© íë¡ê·žëšì ì¶ê°íë ììŽëìŽì ëí ìë¹ ì§ììŽ ììµëê¹? ëë ê·žê²ì ëí ì ìì ìì±í ì ììµëë€. 묞ë²ì ìŒë¡ë ê·žê² ê°ì¥ ì¬ìŽ êžžìŽëŒê³ ìê°í©ëë€.
íì¬ë¡ìë ìëëë€. ì°ëŠ¬ë ê³ ì°š ì í ê³µê°ì 곌ë¶í íŽê²°ì ë£ê³ ì¶ì§ ììµëë€. íë¡ìžì€ë ë€ì ë³µì¡íë©° ì í 맀ê°ë³ì륌 ì ì¶íêž° ìí ì¬ë¬ íšì€ì 컚í ì€íž íì ìžì ë±ì í¬íší©ëë€. ë ëì ììë¡ ìŽ ìì ì ìííë ê²ì 뚌ì ë§ì ìì ìŽ íìíê³ ë ë²ì§žë¡ ì²ëŠ¬í ì€ë¹ê° ëì§ ìì ì±ë¥ 묞ì ê° ë°ìí©ëë€. ìê° ìž.
@mhegazy ë #24897ì ìµê·Œ ìì ì ê°ìí ë ìŽì ëí íì ì ì¥ìŽ ì í ë°ëì§ ìììµëê¹?
$Call
ì íìŒë¡ ì룚ì
ì ì¶ìí ì ìë ëª ê°ì§ 묞ì ê° ìë ê² ê°ìµëë€. $Call
ì íì ë ëì ì¢
ë¥ì ì íì ì뮬ë ìŽížíë ë¹êµì ê°ëší ë°©ë²ì 묞ì ìŽ ê²ì
ëë€. ì륌 ë€ìŽ https://gist.github.com/hallettj/0fde5bd4c3ce5a5f6d50db6236aaa39e 륌 ì°žì¡°íììì€( $PropertyType
ë° $ObjMap
ì ì¬ì©ì $Call
ë¡ ë첎). ížì§: ì¶ê° ì: https://github.com/facebook/flow/issues/30#issuecomment -346674472
ê·žë¬í êž°ë¥ì í늌ììŽ ë§ì 묞ì ì ëí í©ëŠ¬ì ìž ê³µíµ ì룚ì ì ì°Ÿì TypeScriptì ì€ì 곌 ìŒì¹í ê²ì ëë€. ê·žë ì£ ?
í¹ì ìžì ì§í©ì ì íšì±ì ê²ì¬íë €ë ê²œì° í¹ì ë€ë¥ž ë³ì¹ê³Œ íšê»
ReturnTypeOf<T>
륌 ìì±í ì ììŒë¯ë¡ ì¡°ê±Žë¶ ì íì ìŽì ìŽê²ì í¬ê² êŽë šìŽ ìê² ë§ëëë€. ê·žë€ì 곌ë¶í íŽê²°ì í ì ìì§ë§ ì°ëŠ¬ë ìŽ êž°ë¥ìŽ ê·ž ì¬ì© ì¬ë¡ì ëí ë³µì¡ì±ë§íŒ ê°ì¹ê° ìë€ê³ ìê°íì§ ììµëë€.
@RyanCavanaugh @mhegazy
ì¡°ê±Žë¶ ì íì ì¬ì©íì¬ ìì
ì ìíí ì ìë€ë ë° ëìí©ëë€. User.avatar
륌 User extends { avatar: infer T } ? T : never
ë¡ ë€ì ìŽë€ë©Ž 컎íìŒë¬ì ì¶ê°ì ìž ë³µì¡ì±ì ê°ì žì€ì§ ìì ê²ìŽëŒê³ ìê°í©ëë€. ì륌 ë€ìŽ ë€ì곌 ê°ìŽ ìì±í ì ììµëë€.
export type Avatar = User extends { avatar: infer T } ? T : never;
ê°ìŽ
export type Avatar = User.avatar;
ê°ë ì±ì í¥ììí€êž° ìíŽ.
ìŒë¶ ë°ìŽí°ë¥Œ ë¡ë ë° ë³ííê³ ë€ì곌 ê°ì findUser íšìë¡ ëëë€ê³ ê°ì í©ëë€.
export function findUser() {
return {
username: 'johndoe',
avatar: {
lg: '1.jpg',
s: '2.jpg'
},
repos: [
{
name: 'ts-demo',
stats: {
stars: 42,
forks: 4
},
pull_requests: [
{ date: '2019-08-19', tags: ['bug', 'agreed-to-cla'] },
{ date: '2019-08-10', tags: ['bug', 'includes-tests'] },
{ date: '2019-08-07', tags: ['feature'] }
]
}
]
};
}
맀íë ì íì ì¶ë¡ ëë¶ì ë€ì곌 ê°ìŽ íšììì ì íì ì¶ì¶í ì ììµëë€.
export type User = ReturnType<typeof findUser>;
export type Avatar = User extends { avatar: infer T } ? T : never;
ì ì: ìŽê²ì ê°ì ê²ìŒë¡ íê°ëìŽìŒ í©ëë€.
export type Avatar = User.avatar;
ëí User.avatar
ê° never
ì íìŽ ìëìŽìŒ íë€ê³ 죌ì¥í ìë ììµëë€.
ë ë§ì ì
export type Repositories = User extends { repos: infer T } ? T : never;
export type Repository = User extends { repos: (infer T)[] } ? T : never;
export type RepositoryStats = Repository extends { stats: infer T } ? T : never;
export type PullRequests = Repository extends { pull_requests: (infer T)[] } ? T : never;
export type PullRequest = Repository extends { pull_requests: (infer T)[] } ? T : never;
export type Tags = PullRequest extends { tags: infer T } ? T : never;
export type Tag = PullRequest extends { tags: (infer T)[] } ? T : never;
export type Repositories = User.repos;
export type Repository = User.repos[];
export type RepositoryStats = User.repos[].stats;
export type PullRequests = User.repos[].pull_requests;
export type PullRequest = User.repos[].pull_requests[];
export type Tags = User.repos[].pull_requests[].tags;
export type Tag = User.repos[].pull_requests[].tags[];
ì€ì²© ìì±ì í ë²ì 맀íí ë ë¬Žìš ìŒìŽ ìŒìŽëê³ ìëì§ ëª ííì§ ììµëë€.
export type Tag2 = User extends { repos: { pull_requests: { tags: (infer T)[] }[] }[] } ? T : never;
ìŽê²ì ë§ì ê²ì ë°í ê²ì ëë€.
export type Tag = User.repos[].pull_requests[].tags[];
export class Hello {
static world = 'world';
world = 42;
}
export type ThisWillBeANumber = Hello extends { world: infer T } ? T : never;
export type ThisWillBeANumber = Hello.world;
export type ThisWillBeAString = (typeof Hello) extends { world: infer T } ? T : never;
export type ThisWillBeAString = (typeof Hello).world;
@lukaselmer ê·žë¥ ìíë ê² ê°ìµëë€
export type Avatar = User["avatar"];
ì€ë ìëíë
@lukaselmer ê·žë¥ ìíë ê² ê°ìµëë€
export type Avatar = User["avatar"];
ì€ë ìëíë
ê·žê²ìŽ ë°ë¡ ëŽê° ì°Ÿë ê²ì ëë€. 묞ì ìì ê²ìíì§ë§ ì°Ÿì§ ëª»íìµëë€. ê°ì¬í©ëë€!
ìŽê²ì ížëë¶ì ìŒë¶ì ëê¹, ìëë©Ž ìŽê²ìŽ ìŽë»ê² ìëíëì§ì ëí ê³µì 묞ìê° ììµëê¹? ëë ê·žê²ì ì¬ì©íë ë°©ë²ì ëíŽ êœ€ ìµìíì§ë§ ì¬ëë€ì 묞ìë¡ ìëŽíë €ê³ í ë ëŽê° ì°Ÿì ì ìë ê²ì typeof ê°ëë¿ìŽë©° ìŽë ì ë§ ìì í ë€ëŠ ëë€.
ê·žëì ì ë ìŽ ì ììŽ 2015ë ë¶í° íê²šì ž ëìê³ ìë 목í ì€ íëë ìží°íìŽì€ì ëšìŒ ìì± ì íì ì»ë ê²ìŽììì ìê² ëììµëë€.
interface a {
foo: bar;
/* more types */
}
const example = (fooNeeded: [magic] a.foo ) => {};
ìŽê²ìŽ 5ë íìë ì¬ì í ë¶ê°ë¥íë€ê³ ê°ì íë ê²ìŽ ë§ìµëê¹?
@MFry ë€ì 구묞ì ì°Ÿê³ ìë€ê³ ìê°í©ëë€. a['foo']
ìŽì ëí íŽê²°ì± ìŽ ìì§ ìëì§ ìê³ ììµëê¹?
ëë ë€ì곌 ê°ì ê²ì ì»ìŒë €ê³ ë žë ¥ ì€ìŽë€.
declare function something<A, B>(): void;
type Payload = string;
const hello = something<{}, Payload>();
declare function doThing<T extends ReturnType<typeof something>>(arg: T): { payload: unknown };
doThing(hello).payload === 123; // this should validate to a string aka type Payload
https://www.typescriptlang.org/play/index.html?ts=4.0.0-dev.20200512#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXwGccBbEDACy1QHMAeAQQBp4AhAPgAoBKALngDccWYAG4AUGIwBPAA4IAClCkQcUYPAC8hDDCrVxYsHgIZ45EBBWbCJMpRq0A3gF9mi5auCcuB0JFgIKOjYePDAOAAq9nQR8CAAHhggqMAE8ABKZMgwqBGyILTScjiINqQUemycsNR8EbzwjvAySipqfGgA1qg4AO74zr6R0RzmljhcAHQtHmqaGloAjABMAMwi8AD0m -AVaQTkOMgQ6vxQEMJQSbs48FDaujR3nfdFCq2eYkA
ìë
íìžì @maraisr ë¹ì ìŽ ë¬ì±íë €ë ê²ìŽ 100% íì€íì§ ììµëë€. ê·íì ììì something
ë ë ê°ì§ ì íì ì¬ì©íì§ë§ ì¬ì©íì§ ììµëë€ hello
ë íì void
ê° ë ê²ì ë°í ê°ì
ëë€. ë°ëŒì doThing
$ë ìŽë€ ìì ììë string
ì íì ë³Žì§ ììµëë€.
ìë§ë ìëì ê°ì ê²ìŽ ë¹ì ìŽ ìíë ê²ì ëê¹?
declare function something<ReturnType>(): ReturnType;
type Payload = string;
const hello = () => something<Payload>();
declare function doThing<F extends () => any>(f: F): { payload: ReturnType<F> };
doThing(hello).payload === 'a string';
ì ì - ì£ì¡í©ëë€. ì ìí ëµë³ ê°ì¬í©ëë€!! :100: @acutmore
void
ë íŽë¹ íšìì ë°í ì íìŽ êŽë šìŽ ììì ëíëŽêž° ìí ê²ì
ëë€. ìŽ 2ê°ì§ ì íì ë€ë¥ž ì ë€ëŠ ì íìŒë¡ ì ë¬ëìŽ ê¶ê·¹ì ìŒë¡ ìžìì ì¬ì©ë©ëë€.
ë€ì곌 ê°ì ê²:
declare function something<A, B>(a: MyComplexGeneric<A>, b: B[]): { somethingA: number, somethingB: number };
// Those 2 generics influence the return object so they do get used as such. And the 2 arguments are roughly that. Its an object and an array, more-or-less.
ëŽ doThing
íšìë 첫 ë²ì§ž( A
) ì ë€ëŠìŽ 묎ììžì§ ì€ì ë¡ ì 겜 ì°ì§ ìì§ë§ ë ë²ì§ž( B
)ê° ë¬Žììžì§ë ìêŽí©ëë€.
ëŽ ìì ì ì¬ì© ì¬ë¡ìì something
ê° doThing
ìì ìœì ì ìë ë¶ìì©ì ìííë ê²ì íìžíììì€.
ë°ëŒì ëšìí íšìì ReturnTypeì ê°ì žì¬ ì ììµëë€. ìì±ë íšìì ì ë€ëŠì ìŽë»ê²ë 빚ìë€ì¬ìŒ í©ëë€.
ìŽ ì¿ŒëŠ¬ê° ìŽ ë¬žì ì ë²ì륌 ë²ìŽë¬ë€ê³ ìê°ëë©Ž StackOverflowì ëí ëŽ ì¬ì ì ê³ìíììì€!
@maraisr ì¶ê° ì 볎 ê°ì¬í©ëë€.
doThing
ìì something
ìì ìëì B
ì íì ê°ì žì€ë €ë©Ž ìŽë»ê²ë hello
ì ì ë¬íŽìŒ í©ëë€. TypeScriptë hello
ë§ ë³Žê³ ììŒë©° ëììŽ ììŒë©Ž something
ì ë°í ì íìžì§ ìì§ ëª»í©ëë€.
ìŽê²ìŽ ê°ë¥í í ê°ì§ ë°©ë²ì ëë€.
/** Create a type that can store some extra type information **/
interface SomethingResult<T> {
__$$__: T;
somethingA: number;
somethingB: number;
}
declare function something<A, B>(): SomethingResult<B>;
type Payload = string;
const hello = something<{}, Payload>();
declare function doThing<Result extends SomethingResult<any>>(arg: Result): { payload: Result['__$$__'] };
doThing(hello).payload === 1123; // error because `payload` is of type string
interface User {
avatar: string;
}
interface UserData {
someAvatar: User['avatar'];
}
@RyanCavanaugh ì ë«íìëì? ì¡°ê±Žë¶ ì íì ìŽ ë¬žì ì ë€ë¥ž ë§ì ì¬ì© ì¬ë¡ë¥Œ íŽê²°íì§ ëª»íë©° ìŽê²ìŽ ë³í©ëë©Ž ë§ì ìŒìŽ ê°ë¥íŽì§ëë€.
ì ë 몚ë ë©ìë ížì¶ì "í¬ìžíž ìë" ë²ì ìŒë¡ ì íí ì ìë íšì륌 ìì
ì€ì
ëë€(ì: [].map(() => n > 5)
ê° map(() => n > 5)([])
ë¡ ë°ëê³ ëëœë ì ìŒí ê²ì ì¡°ê±Žë¶ ì í ë° infer
ë ì ë€ëŠì ê°ì§í ì ììŒë¯ë¡ ì ë€ëŠ íšììì ìŒë¶ ì íì unknown
ë¡ ëìµëë€.
íšì륌 "ížì¶"íì¬ ì í( typeof myFunc(() => Either<string,number>)
)ì ê°ì žì¬ ì ìë€ë©Ž ìŽ êž°ë¥ì ê°ì§ ì ìê³ (íì¬ë ë¶ê°ë¥), ë€ë¥ž ë§ì ìì
ì íšì¬ ë ìœê² ìíí ì ììµëë€(HKT ë±). .)
$Call
íšì(ì: íëŠ)륌 ìíí ì ìë ë³µì¡ì±ìŽ ë§€ì° ëìµëê¹? typescriptê° ìŽë¯ž ìëìŒë¡ ìííë ê²ì²ëŒ ë껎ì§ëë€.
@nythrox ì°ëŠ¬ë ìŽê²ìŽ ìŽëí ì ìë êµ¬ë¬žë¡ ì íŒëìŽ ìŽë€ ì íì ëë¬íêž° ìíŽ íìí 겜ì°ë³Žë€ ì€ìíë€ê³ ìê°íì§ ììµëë€. ížì¶ ííìì íŽê²°íë í¹ì ì¬ë¡ë ë€ë¥ž ê³³ìì ì¶ì ë©ëë€. "ìŽë€ ííìŽë íì©íëŒ"ë OPì ì ìì ì°ëŠ¬ê° ìê°íêž°ì ìžìŽì ì í©íì§ ìì ê²ì ëë€.
@RyanCavanaugh ì, ìê² ìµëë€. ìëµíŽ 죌ì ì ê°ì¬í©ëë€. íšì ížì¶ì íŽê²°íë ëì ìŽë€ 묞ì ê° ì¶ì ëëì§ ìê³ ììµëê¹?
ëë ìœê°ì 죌ì륌 ê²ìíê³ íšì ížì¶ ì ížëŠ¬í° ì íì ëí 묞ì 륌 ì°Ÿì§ ëª»íìµëë€. ëŽê° ì°Ÿì ì ìŒí ì°žì¡°ë #20352ì ììëë°, ìŽ ë¬žì ë ìŽ ë¬žì ì ë€ì ì°ê²°ëììµëë€.
ížì¶ ííìì íŽê²°íë í¹ì ì¬ë¡ë ë€ë¥ž ê³³ìì ì¶ì ë©ëë€.
@RyanCavanaugh ë€ë¥ž 곳곌 ì°ê²°ëë ê²ì ìŒëì ëìê² ìµëê¹? ð
@tjjfvi #37181ì ë 구첎ì ìŒë¡ ì ë ¥ì êž°ë°ìŒë¡ íšì륌 íŽê²°íë ê²ì êŽí ê²ì ëë€. ë¹ì ìŽ ì°Ÿê³ ìë ê²ìŒ ì ììµëë€.
@acutmore íëŠê³Œ ì ì¬í $Call
ì ížëŠ¬í° ëë ìŽë¥Œ 구íí ì ìë ë€ë¥ž 구묞ì ëíŽ êµ¬ì²Žì ìŒë¡ ìŽìŒêž°íê³ ììì§ë§ ê·žê²ì ëŽê° ì°Ÿê³ ìë ê²ê³Œ ë€ì ìŒì¹í©ëë€. ì ê·Œ ë°©ììŽ ìŽìíë€ê³ ì ìíì§ë§ ë§í¬ì ê°ì¬ë늜ëë€.
ê°ì¥ ì ì©í ëêž
#17961ìì PRì ìŽììµëë€.