ãããé©åã«ã¿ã€ããã§ãã¯ããããšãã§ããã°ããã€ã©ãŒãã¬ãŒãã®ãªãããã¯ã¹ã€ã³ãå®å šã«ãµããŒãã§ããŸãã
declare function Blah<T>(target: T): T & {foo: number}
<strong i="6">@Blah</strong>
class Foo {
bar() {
return this.foo; // Property 'foo' does not exist on type 'Foo'
}
}
new Foo().foo; // Property 'foo' does not exist on type 'Foo'
åãããšãã¡ãœããã«ã圹ç«ã¡ãŸãã
class Foo {
<strong i="6">@async</strong>
bar(x: number) {
return x || Promise.resolve(...);
}
}
éåæãã³ã¬ãŒã¿ã¯ãæ»ãå€ã®ã¿ã€ããPromise<any>
ã«å€æŽããããšã«ãªã£ãŠããŸãã
@Gaelan ãããã¯ãŸãã«ç§ãã¡ãããã§å¿ èŠãšããŠãããã®ã§ãïŒ ããã¯ã¹ã€ã³ãæäœããã®ãèªç¶ã«ãªããŸãã
class asPersistent {
id: number;
version: number;
sync(): Promise<DriverResponse> { ... }
...
}
function PersistThrough<T>(driver: { new(): Driver }): (t: T) => T & asPersistent {
return (target: T): T & asPersistent {
Persistent.call(target.prototype, driver);
return target;
}
}
@PersistThrough(MyDBDriver)
Article extends TextNode {
title: string;
}
var article = new Article();
article.title = 'blah';
article.sync() // Property 'sync' does not exist on type 'Article'
ãã®ããã«+1ã ãããå®è£ ããã®ã¯é£ããããšã¯ç¥ã£ãŠããŸããããã³ã¬ãŒã¿ã®ãã¥ãŒããŒã·ã§ã³ã»ãã³ãã£ã¯ã¹ã«ã€ããŠåæã«éããã®ã¯ããããé£ããã§ãããã
+1
ããã®äž»ãªå©ç¹ãåã·ã°ããã£ã«è¿œå ã®ã¡ã³ããŒãå°å ¥ããããšã§ããå Žåã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžã§ãã§ã«ãããè¡ãããšãã§ããŸãã
interface Foo { foo(): number }
class Foo {
bar() {
return this.foo();
}
}
Foo.prototype.foo = function() { return 10; }
new Foo().foo();
ãã³ã¬ãŒã¿ããã¯ã©ã¹ã匷å¶çã«å€æŽããããã«ã³ã³ãã€ã©ãåŒã³åºãå¿ èŠã®ããå®éã®é¢æ°ã§ããå Žåãããã¯åå®å šèšèªã§ããIMHOã§è¡ãæ £çšçãªããšã§ã¯ãªãããã§ãã
@masaeeduè£ é£Ÿãããã¯ã©ã¹ã«éçã¡ã³ããŒãè¿œå ããããã®åé¿çãç¥ã£ãŠããŸããïŒ
@davojanãã¡ããã§ãã ã©ããïŒ
class A { }
namespace A {
export let foo = function() { console.log("foo"); }
}
A.foo();
ã¡ãœãããè£ é£Ÿãããšãã«ãã¯ã©ã¹ã«_multiple_ããããã£ãå°å ¥ã§ãããšäŸ¿å©ã§ãïŒããšãã°ãã²ãã¿ãŒã«é¢é£ä»ããããã»ãã¿ãŒãçæãããã«ããŒããŸãã¯ãããã®ç·ã«æ²¿ã£ããã®ïŒ
connect
ã®react-reduxã¿ã€ãã³ã°ã¯ã³ã³ããŒãã³ããåãåãããã®å°éå
·ã«reduxãä»ããŠåä¿¡ããæ¥ç¶ãããå°éå
·ãå«ãŸããŠããªãå€æŽãããã³ã³ããŒãã³ããè¿ããŸãããTSã¯connect
ã®å®çŸ©ã次ã®ããã«èªèããªãããã§ãããã®åé¡ã«ãããã³ã¬ãŒã¿ã 誰ããåé¿çãæã£ãŠããŸããïŒ
ClassDecorator
åã®å®çŸ©ãå€æŽããå¿
èŠããããšæããŸãã
çŸåšã¯declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
ã§ãã å€åããã¯ã«å€æŽãããå¯èœæ§ããããŸã
declare type MutatingClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
declare type WrappingClassDecorator = <TFunction extends Function, TDecoratorFunction extends Function>(target: TFunction) => TDecoratorFunction;
declare type ClassDecorator = MutatingClassDecorator | WrappingClassDecorator;
æããã«ååã¯ã²ã©ãããã®çš®ã®ããšãããŸããããã©ããã¯ããããŸããïŒç§ã¯Babelã¢ããªãtypescriptã«å€æããããšããŠããŠããããæã£ãŠããŸãïŒã
@joytåé¡ã®éã³å Žã®åæ§ç¯ãæäŸã§ããŸããïŒ ç§ã¯react-reduxã䜿çšããŠããŸããããåã«è¿°ã¹ãããã«ãåã®åœ¢ç¶ã«å¿ èŠãªæ¡åŒµæ©èœã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžã䜿çšããŠå®£èšã§ãããšæããŸãã
@masaeeduã¯å¯åéšåã®åºæ¬çãªå èš³ã§ãââã
åºæ¬çã«ããã³ã¬ãŒã¿ã¯Reactã³ã³ããŒãã³ãã«å€æ°ã®å°éå ·ãæäŸããããããã³ã¬ãŒã¿ã®ãžã§ããªãã¯ã¿ã€ãã¯ãã¹ãŒããŒã»ããã§ã¯ãªããè£ é£Ÿãããã³ã³ããŒãã³ãã®ãµãã»ããã§ãã
ããã圹ç«ã€ãã©ããã¯ããããŸããããå®è¡äžå¯èœãªãµã³ãã«ããŸãšããŠãå®éã®ã¿ã€ãã瀺ããŠã¿ãŸããã
// React types
class Component<TProps> {
props: TProps
}
class ComponentClass<TProps> {
}
interface ComponentDecorator<TOriginalProps, TOwnProps> {
(component: ComponentClass<TOriginalProps>): ComponentClass<TOwnProps>;
}
// Redux types
interface MapStateToProps<TStateProps, TOwnProps> {
(state: any, ownProps?: TOwnProps): TStateProps;
}
// Fake react create class
function createClass(component: any, props: any): any {
}
// Connect wraps the decorated component, providing a bunch of the properies
// So we want to return a ComponentDecorator which exposes LESS than
// the original component
function connect<TStateProps, TOwnProps>(
mapStateToProps: MapStateToProps<TStateProps, TOwnProps>
): ComponentDecorator<TStateProps, TOwnProps> {
return (ComponentClass) => {
let mappedState = mapStateToProps({
bar: 'bar value'
})
class Wrapped {
render() {
return createClass(ComponentClass, mappedState)
}
}
return Wrapped
}
}
// App Types
interface AllProps {
foo: string
bar: string
}
interface OwnProps {
bar: string
}
// This does not work...
// @connect<AllProps, OwnProps>(state => state.foo)
// export default class MyComponent extends Component<AllProps> {
// }
// This does
class MyComponent extends Component<AllProps> {
}
export default connect<AllProps, OwnProps>(state => state.foo)(MyComponent)
//The type exported should be ComponentClass<OwnProps>,
// currently the decorator means we have to export ComponentClass<AllProps>
å®å šã«æ©èœããäŸãå¿ èŠãªå Žåã¯ã httpsïŒ//github.com/jaysoo/todomvc-redux-react-typescriptãŸãã¯å¥ã®ãµã³ãã«react / redux / typescriptãããžã§ã¯ãããã«ããŠã³ããããšããå§ãããŸãã
https://github.com/wycats/javascript-decorators#class -declarationã«ãããšãææ¡ãããdeclare type WrappingClassDecorator = <TFunction extends Function, TDecoratorFunction extends Function>(target: TFunction) => TDecoratorFunction;
ã¯ç¡å¹ã§ãããšç解ããŠããŸãã
ä»æ§ã«ãããšïŒ
@F("color")
<strong i="6">@G</strong>
class Foo {
}
ã«ç¿»èš³ãããŸãïŒ
var Foo = (function () {
class Foo {
}
Foo = F("color")(Foo = G(Foo) || Foo) || Foo;
return Foo;
})();
ãããã£ãŠãç§ããããæ£ããç解ããŠããã°ã次ã®ããšãåœãŠã¯ãŸãã¯ãã§ãã
declare function F<T>(target: T): void;
<strong i="13">@F</strong>
class Foo {}
let a: Foo = new Foo(); // valid
class X {}
declare function F<T>(target: T): X;
<strong i="16">@F</strong>
class Foo {}
let a: X = new Foo(); // valid
let b: Foo = new Foo(); // INVALID
declare function F<T>(target: T): void;
declare function G<T>(target: T): void;
<strong i="19">@F</strong>
<strong i="20">@G</strong>
class Foo {}
let a: Foo = new Foo(); // valid
class X {}
declare function F<T>(target: T): void;
declare function G<T>(target: T): X;
<strong i="23">@F</strong>
<strong i="24">@G</strong>
class Foo {}
<strong i="25">@G</strong>
class Bar {}
<strong i="26">@F</strong>
class Baz {}
let a: Foo = new Foo(); // valid
let b: X = new Foo(); // INVALID
let c: X = new Bar(); // valid
let d: Bar = new Bar(); // INVALID
let e: Baz = new Baz(); // valid
class X {}
declare function F<T>(target: T): X;
declare function G<T>(target: T): void;
<strong i="29">@F</strong>
<strong i="30">@G</strong>
class Foo {}
<strong i="31">@G</strong>
class Bar {}
<strong i="32">@F</strong>
class Baz {}
let a: X = new Foo(); // valid
let b: Bar = new Bar(); // valid
let c: X = new Baz(); // valid
let d: Baz = new Baz(); // INVALID
@blai
ããªãã®äŸã®ããã«ïŒ
class X {} declare function F<T>(target: T): X; <strong i="9">@F</strong> class Foo {} let a: X = new Foo(); // valid let b: Foo = new Foo(); // INVALID
F
ãX
ã«æºæ ããã¯ã©ã¹ãè¿ãããšãæå³ããŠãããšæããŸãïŒ X
ã®ã€ã³ã¹ã¿ã³ã¹ã§ã¯ãããŸããïŒïŒ äŸãã°ïŒ
declare function F<T>(target: T): typeof X;
ãã®å Žåãã¢ãµãŒã·ã§ã³ã¯æ¬¡ã®ããã«ãªããŸãã
let a: X = new Foo(); // valid
let b: Foo = new Foo(); // valid
ãããã®let
ã¹ããŒãã¡ã³ãã®ã¹ã³ãŒãå
ã«ããFoo
ã¯ããã³ã¬ãŒã¿ãŒã«ãã£ãŠå€æŽãããŠããŸãã å
ã®Foo
ã«ã¯ã¢ã¯ã»ã¹ã§ããªããªããŸããã ããã¯å®è³ªçã«æ¬¡ãšåçã§ãã
let Foo = F(class Foo {});
@nevirãããããªãã¯æ£ããã 説æããŠãããŠããããšãã
ã¡ãªã¿ã«ãå€æŽãããã¯ã©ã¹ã¿ã€ããç¡å¹ã«ãããã§ãã¯ããªãã«ããã®ã¯æ¯èŒçç°¡åãªããã§ãã
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 06591a7..2320aff 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -11584,10 +11584,6 @@ namespace ts {
*/
function getDiagnosticHeadMessageForDecoratorResolution(node: Decorator) {
switch (node.parent.kind) {
- case SyntaxKind.ClassDeclaration:
- case SyntaxKind.ClassExpression:
- return Diagnostics.Unable_to_resolve_signature_of_class_decorator_when_called_as_an_expression;
-
case SyntaxKind.Parameter:
return Diagnostics.Unable_to_resolve_signature_of_parameter_decorator_when_called_as_an_expression;
}
/** Check a decorator */
function checkDecorator(node: Decorator): void {
const signature = getResolvedSignature(node);
const returnType = getReturnTypeOfSignature(signature);
if (returnType.flags & TypeFlags.Any) {
@@ -14295,9 +14291,7 @@ namespace ts {
let errorInfo: DiagnosticMessageChain;
switch (node.parent.kind) {
case SyntaxKind.ClassDeclaration:
- const classSymbol = getSymbolOfNode(node.parent);
- const classConstructorType = getTypeOfSymbol(classSymbol);
- expectedReturnType = getUnionType([classConstructorType, voidType]);
+ expectedReturnType = returnType;
break;
case SyntaxKind.Parameter:
}
ããããç§ã¯ãã³ã³ãã€ã©ãŒãå€æŽãããã¯ã©ã¹ã®æ£ããåå®çŸ©ãåºåããããã«ããã®ã«ååãªç¥èããããŸããã ç§ã¯æ¬¡ã®ãã¹ããè¡ã£ãŠããŸãïŒ
ãã¹ã/ã±ãŒã¹/é©åæ§/ãã³ã¬ãŒã¿/ã¯ã©ã¹/ãã³ã¬ãŒã¿OnClass10.ts
// <strong i="10">@target</strong>:es5
// <strong i="11">@experimentaldecorators</strong>: true
class X {}
class Y {}
declare function dec1<T>(target: T): T | typeof X;
declare function dec2<T>(target: T): typeof Y;
<strong i="12">@dec1</strong>
<strong i="13">@dec2</strong>
export default class C {
}
var c1: X | Y = new C();
var c2: X = new C();
var c3: Y = new C();
ãã¹ã/ããŒã¹ã©ã€ã³/ããŒã«ã«/decoratorOnClass10.typesãçæããŸã
=== tests/cases/conformance/decorators/class/decoratorOnClass10.ts ===
class X {}
>X : X
class Y {}
>Y : Y
declare function dec1<T>(target: T): T | typeof X;
>dec1 : <T>(target: T) => T | typeof X
>T : T
>target : T
>T : T
>T : T
>X : typeof X
declare function dec2<T>(target: T): typeof Y;
>dec2 : <T>(target: T) => typeof Y
>T : T
>target : T
>T : T
>Y : typeof Y
<strong i="17">@dec1</strong>
>dec1 : <T>(target: T) => T | typeof X
<strong i="18">@dec2</strong>
>dec2 : <T>(target: T) => typeof Y
export default class C {
>C : C
}
var c1: X | Y = new C();
>c1 : X | Y
>X : X
>Y : Y
>new C() : C
>C : typeof C
var c2: X = new C();
>c2 : X
>X : X
>new C() : C
>C : typeof C
var c3: Y = new C();
>c3 : Y
>Y : Y
>new C() : C
>C : typeof C
ç§ã¯æåŸ
ããŠããŸãã
>C: typeof C
ã¯>C: typeof X | typeof Y
ã«ãªããŸã
ãã®æ©èœã®ã±ãŒã¹ã¹ã¿ãã£ãšããŠreact-reduxã®connect
ã«èå³ããã人ã®ããã«ãç§ã¯https://github.com/DefinitelyTyped/DefinitelyTyped/issues/9951ãæåºããŠãåé¡ã1ãæã§è¿œè·¡ããŸããã
ãã®åé¡ã«é¢ãããã¹ãŠã®ã³ã¡ã³ããèªã¿ãŸãããããã³ã¬ãŒã¿ã®çœ²åã¯ãã©ãããããã¯ã©ã¹ã§äœãã§ããããå®éã«ã¯ç€ºããŠããªããšããèãããããŸãã
ãããèããŠã¿ãŸãããïŒ
function decorator(target) {
target.prototype.someNewMethod = function() { ... };
return new Wrapper(target);
}
次ã®ããã«å
¥åããå¿
èŠããããŸãã
declare function decorator<T>(target: T): Wrapper<T>;
ãããããã®çœ²åã¯ããã³ã¬ãŒã¿ãã¿ãŒã²ããã®ãããã¿ã€ãã«æ°ãããã®ãè¿œå ããããšã瀺ããŠããŸããã
äžæ¹ãããã¯ããã³ã¬ãŒã¿ãå®éã«ã©ãããŒãè¿ããããšã瀺ããŠããŸããã
declare function decorator<T>(target: T): T & { someMethod: () => void };
ããã«é¢ãããã¥ãŒã¹ã¯ãããŸããïŒ ããã¯ã¡ã¿ããã°ã©ãã³ã°ã«ãšã£ãŠéåžžã«åŒ·åã§ãïŒ
ãã®åé¡ãžã®ããç°¡åãªã¢ãããŒãã¯ã©ãã§ããïŒ ãã³ã¬ãŒããããã¯ã©ã¹ã®å Žåãæ§æç³è¡£ãšããŠã¯ã©ã¹åããã³ã¬ãŒã¿ã®æ»ãå€ã«ãã€ã³ãããŸãã
declare function Blah<T>(target: T): T & {foo: number}
<strong i="6">@Blah</strong>
class Foo {
bar() {
return this.foo; // Property 'foo' does not exist on type 'Foo'
}
}
// is desugared to
const Foo = Blah(class Foo {
// this.foo is not available here
})
new Foo.foo // foo is available here.
å®è£ ã«é¢ããŠã¯ãããã«ãããè£ é£Ÿãããã¯ã©ã¹ã®1ã€ã®åæã·ã³ãã«ãå°å ¥ãããŸãã ãŸããå ã®ã¯ã©ã¹åã¯ã¯ã©ã¹æ¬äœã¹ã³ãŒãã«ã®ã¿ãã€ã³ããããŸãã
@HerringtonDarkholmeããã¯ãæãŸããè¡šçŸåã®ã»ãšãã©ãæäŸãããããŸãå®çšçãªã¢ãããŒãã«ãªããšæããŸãã ããæ¡ïŒ
ãã€ã絶察ã«èŠãã
ç§ã¯ããAngular2ãŸãã¯Aureliaã®ã¯ã©ã¹ãäœæããŸããããã¯æ¬¡ã®ããã«ãªããŸãã
import {Http} from 'aurelia-fetch-client';
import {User} from 'models';
// accesses backend routes for 'api/user'
<strong i="9">@autoinject</strong> export default class UserService {
constructor(readonly http : Http) { }
readonly resourceUrl = 'api/users';
async get(id: number) {
const response = await this.http.fetch(this.resourceUrl);
const user = await response.json() as User;
return user;
}
async post(id: number, model: { [K in keyof User]?: User[K] }) {
const response = await this.http.post(`${this.resourceUrl}/`${id}`, model);
return await response.json();
}
}
ç§ãæžãããã®ã¯
ãã³ã¬ãŒã¿/api-client.ts
import {Http} from 'aurelia-fetch-client';
export type Target = { name; new (...args): { http: Http }};
export default function apiClient<T extends { id: string }>(resourceUrl: string) {
return (target: Target) => {
type AugmentedTarget = Target & { get(id: number): Promise<T>, post(id, model: Partial<T>) };
const t = target as AugmentedTarget;
t.prototype.get = async function (id: number) {
const response = await this.http.fetch(resourceUrl);
return await response.json() as T;
}
}
}
ãããŠãç§ã¯ãããäžè¬çã«æ¬¡ã®ããã«é©çšããããšãã§ããŸã
import {Http} from 'aurelia-fetch-client';
import apiClient from ./decorators/api-client
import {User} from 'models';
@apiClient<User>('api/users') export default class UserService {
constructor(readonly http : Http) { }
}
åå®å šæ§ã倱ãããšã¯ãããŸããã ããã¯ãã¯ãªãŒã³ã§è¡šçŸåè±ããªã³ãŒããæžãããã®æ©æµã«ãªããŸãã
ãã®åé¡ã埩掻ãããŸãã
ïŒ13743ããªãªãŒã¹ãããããã¯ã¹ã€ã³ã®ãµããŒãããã®èšèªã§è¡ãããããã«ãªã£ãã®ã§ãããã¯éåžžã«äŸ¿å©ãªæ©èœã§ãã
@HerringtonDarkholmeã¯ãã®å Žåã«ã¯ããŸãé©ããŠããŸãããããã³ã¬ãŒã¿ã®æ»ãåã宣èšããå¿ èŠããããšãããã€ãã®åçæ©èœã倱ãããŸã...
@ ahejlsberg ã @ mhegazyããã¯å®è¡å¯èœã ãšæããŸããïŒ
å¥ã®äœ¿çšã·ããªãªããããŸããããã®äŒè©±ã§ãŸã ã«ããŒãããŠãããã©ããã¯ããããŸããããããããåãåäžã«ãããŸãã
ã¡ãœããã®åãå®å šã«å€æŽããã¡ãœãããã³ã¬ãŒã¿ãå®è£ ããããšæããŸãïŒæ»ãåããã©ã¡ãŒã¿ã§ã¯ãªããé¢æ°å šäœïŒã äŸãã°
type AsyncTask<Method extends Function> = {
isRunning(): boolean;
} & Method;
// Decorator definition...
function asyncTask(target, methodName, descriptor) {
...
}
class Order {
<strong i="7">@asyncTask</strong>
async save(): Promise<void> {
// Performs an async task and returns a promise
...
}
}
const order = new Order();
order.save();
order.save.isRunning(); // Returns true
JavaScriptã§ã¯å®å
šã«å¯èœã§ãããããã¯æããã«åé¡ã§ã¯ãããŸããããTypeScriptã§ã¯ãè£
食ãããã¡ãœããã®ã¿ã€ãã() => Promise<void>
ããAsyncTask<() => Promise<void>>
ã«å€æŽããããã«asyncTask
ãã³ã¬ãŒã¿ãå¿
èŠã§ãã
ããã¯çŸåšäžå¯èœã§ããããããããã®åé¡ã®åäžã«ãããšç¢ºä¿¡ããŠããŸããïŒ
@codeandcatsããªãã®äŸã¯ãç§ãããã«ããã®ãšãŸã£ããåããŠãŒã¹ã±ãŒã¹ã§ãïŒ
ããã«ã¡ã¯@ohjames ãèš±ããŠãã ãããç§ã¯ããªãã®äŸã暡玢ããã®ã«èŠåŽããŠããŸããããªããéã³å Žã§ãã®ãŸãŸæ©èœãããã®ã«æžãçŽãããšãã§ããå¯èœæ§ã¯ãããŸããïŒ
ããã«ã€ããŠäœãé²å±ã¯ãããŸããïŒ ç§ã¯äžæ¥äžãããé ã®äžã«æã£ãŠããŸãããããã®åé¡ã«æ°ã¥ãããã³ã³ãã€ã©ããããèªèããªãããšã確èªããããã ãã«ãããå®è£ ãã«è¡ããŸããã ããåªãããã®ã³ã°ãœãªã¥ãŒã·ã§ã³ã䜿çšã§ãããããžã§ã¯ããããã®ã§ãåŸã§ãã³ã¬ãŒã¿ãä»ããŠã¯ã©ã¹ã«ã¢ã¿ããããæ¬æ Œçãªãã¬ãŒã«æ¡åŒµããããã®ã¯ã€ãã¯ã·ã³ã°ã«ãã³ãäœæããŸããã
<strong i="6">@loggable</strong>
class Foo { }
ããã«å¿ èŠãªã³ãŒããæžããŸãã
type Loggable<T> = T & { logger: Logger };
function loggable<T extends Function>(target: T): Loggable<T>
{
Object.defineProperty(target.prototype, 'logger',
{ value: Logger.instance() });
return <Loggable<T>> target;
}
logger
ããããã£ã¯å®è¡æã«ç¢ºå®ã«ååšããŸãããæ®å¿µãªããã³ã³ãã€ã©ã«ãã£ãŠååŸãããŸããã
ç¹ã«ããã®ãããªã©ã³ã¿ã€ã æ§é ã¯ã³ã³ãã€ã«æã«å®å šã«é©åã«è¡šçŸã§ããã¯ããªã®ã§ããã®åé¡ã®è§£æ±ºçã確èªããããšæããŸãã
ç§ã¯ä»ã®ãšããç§ãæã«å ¥ããããã ãã«ããããã£ãã³ã¬ãŒã¿ã«èœã¡çããŸããïŒ
function logger<T>(target: T, key: string): void
{
Object.defineProperty(target, 'logger',
{ value: Logger.instance() });
}
ãããŠããã次ã®ãããªã¯ã©ã¹ã«æ·»ä»ããŸã
class Foo {
<strong i="19">@logger</strong> private logger: Logger;
...
ããããããã¯ãåçŽãª@loggable
ã¯ã©ã¹ãã³ã¬ãŒã¿ãããããã¬ãŒãå©çšããã¯ã©ã¹ããšã®å®åæã§ãã (this as Loggable<this>).logger
ã®ããã«ã¿ã€ããã£ã¹ãããããšã¯å¯èœã ãšæããŸããããããçæ³ããã¯ã»ã©é ããã®ã§ãã ããã«é¢åã«ãªããŸãã
äž»ã«https://github.com/jeffijoe/mobx-taskããã³ã¬ãŒã¿ã§åäœãããããšãã§ããªãã£ããããã¢ããªå šäœã§TSãå®è¡ããå¿ èŠããããŸããã ãããããã«è§£æ±ºãããããšãé¡ã£ãŠããŸãã ð
ãã³ã¬ãŒã¿ãšTypeScriptãäžçŽåžæ°ãšããŠæ±ãããAngular2ãšã³ã·ã¹ãã ã§ã¯éåžžã«èç«ããããã®ã§ãã ããã§ãããã³ã¬ãŒã¿ã䜿çšããŠããããã£ãè¿œå ããããšãããšãTypeScriptã³ã³ãã€ã©ã¯ããŒãšèšããŸãã Angular2ããŒã ããã®åé¡ã«ããçšåºŠã®é¢å¿ã瀺ããšæããŸããã
@zajrik TS 2.2以éãé©åãªã¿ã€ãã³ã°ã§ãµããŒããããŠããã¯ã©ã¹ããã¯ã¹ã€ã³ã䜿çšããŠãç®çãéæã§ããŸãã
Loggableããã¯ã¹ã€ã³ã次ã®ããã«å®çŸ©ããŸãã
type Constructor<T> = new(...args: any[]) => T;
interface Logger {}
// You don't strictly need this interface, type inference will determine the shape of Loggable,
// you only need it if you want to refer to Loggable in a type position.
interface Loggable {
logger: Logger;
}
function Loggable<T extends Constructor<object>>(superclass: T) {
return class extends superclass {
logger: Logger;
};
}
ãããŠãããã€ãã®æ¹æ³ã§ããã䜿çšããããšãã§ããŸãã ã¯ã©ã¹å®£èšã®extends
å¥ã®ããããïŒ
class Foo {
superProperty: string;
}
class LoggableFoo extends Loggable(Foo) {
subProperty: number;
}
TSã¯ã LoggableFoo
superProperty
ã logger
ãããã³subProperty
ãããããšãèªèããŠããŸãã
const o = new LoggableFoo();
o.superProperty; // string
o.logger; // Logger
o.subProperty; // number
䜿çšããå ·è±¡ã¯ã©ã¹ãè¿ãåŒãšããŠããã¯ã¹ã€ã³ã䜿çšããããšãã§ããŸãã
const LoggableFoo = Loggable(Foo);
ã¯ã©ã¹ããã¯ã¹ã€ã³ããã³ã¬ãŒã¿ãšããŠäœ¿çšããããšãã§ããŸãããã»ãã³ãã£ã¯ã¹ãå°ãç°ãªããŸããäž»ã«ãã¯ã©ã¹ã«ãµãã¯ã©ã¹åãããã®ã§ã¯ãªããã¯ã©ã¹ããµãã¯ã©ã¹åããããšã§ãã
ã¯ã©ã¹ããã¯ã¹ã€ã³ã«ã¯ããã³ã¬ãŒã¿ãIMOã«æ¯ã¹ãŠããã€ãã®å©ç¹ããããŸãã
logger
ã®å®è£
ã«ãžã£ã³ããããšãã€ã³ã¿ãŒãã§ãŒã¹ã§ã¯ãªããmixin_implementation_ã«ç§»åããŸãã@justinfagnaniããã«ã€ããŠã¯ããã¯ã¹ã€ã³ãèããŠããªãã£ãã®ã§ãããããšãããããŸãã ä»å€Loggable
ããã¯ã¹ã€ã³ãäœæããŠããã¬ãŒã®æ·»ä»ãã¡ã€ã«ã®æ§æãå°ãè¯ãããŸãã extends Mixin(SuperClass)
ã«ãŒãã¯ãTS 2.2ã®ãªãªãŒã¹ä»¥æ¥ããããŸã§ããã¯ã¹ã€ã³ã䜿çšããŠããæ¹æ³ã§ãããããç§ã®å¥œã¿ã§ãã
ç§ã¯ããã¯ã¹ã€ã³ããããã³ã¬ãŒã¿æ§æã®ã¢ã€ãã¢ã奜ã¿ãŸãããããã§ããã®ç¹å®ã®åé¡ã«å¯ŸããŠããçšåºŠã®è§£æ±ºçãåŸãããããšãé¡ã£ãŠããŸãã ç§ã®æèŠã§ã¯ããã³ã¬ãŒã¿ã䜿çšããŠå®åæã®ãªãããã¯ã¹ã€ã³ãäœæã§ããããšã¯ãã³ãŒããããã¯ãªãŒã³ã«ããããã®å€§ããªæ©æµã«ãªãã§ãããã
@zajrikã¯ææ¡ã圹ã«ç«ã£ãããšãããããæããŸããç§ã¯é¡ã£ãŠããŸã
ããã¯ã¹ã€ã³ããã³ã¬ãŒã¿ããããã€ã©ãŒãã¬ãŒããæã£ãŠããããšãç§ã¯ãŸã ããç解ããŠããŸããã æ§æäžã®éã¿ã¯ã»ãŒåãã§ãã
ã¯ã©ã¹ããã¯ã¹ã€ã³ïŒ
class LoggableFoo extends Loggable(Foo) {}
vsãã³ã¬ãŒã¿ïŒ
<strong i="12">@Loggable</strong>
class LoggableFoo extends Foo {}
ç§ã®æèŠã§ã¯ãããã¯ã¹ã€ã³ã¯ãã®æå³ã«ã€ããŠã¯ããã«æ確ã§ããã¹ãŒããŒã¯ã©ã¹ãçæããã¹ãŒããŒã¯ã©ã¹ã¯ã¯ã©ã¹ã®ã¡ã³ããŒãå®çŸ©ããã®ã§ãããã¯ã¹ã€ã³ã¯ããããã¡ã³ããŒãå®çŸ©ããŠããŸãã
ãã³ã¬ãŒã¿ã¯ãã¡ã³ããŒãå®çŸ©ããŠããããŸãã¯å®çŸ©ããŠããªããšã¯æããªãã»ã©å€ãã®ããšã«äœ¿çšãããŸãã åã«ã¯ã©ã¹ãäœãã«ç»é²ããããã¡ã¿ããŒã¿ãããã«é¢é£ä»ããããšãã§ããŸãã
å ¬å¹³ãæãããã«ã @ zajrikãæãã§ããã®ã¯æ¬¡ã®ãšããã§ãã
<strong i="7">@loggable</strong>
class Foo { }
ããã¯ããããã§ã¯ãããããã€ã©ãŒãã¬ãŒããå°ãªãããšã¯ééããããŸããã
ããã¯èšã£ãŠããç§ã¯ããã¯ã¹ã€ã³ãœãªã¥ãŒã·ã§ã³ã倧奜ãã§ãã ç§ã¯ããã¯ã¹ã€ã³ãç©ã§ããããšãå¿ãç¶ããŠããŸãã
æ°ã«ãªãã®ãçŸåšã®ã¯ã©ã¹ã«ããããã£ãè¿œå ããããšã ãã§ããå Žåãããã¯ã¹ã€ã³ã¯åºæ¬çã«1ã€ã®å€§ããªç
©ããããæã€ãã³ã¬ãŒã¿ãšåçã§ã...ã¯ã©ã¹ã«ãŸã ã¹ãŒããŒã¯ã©ã¹ããªãå Žåã¯ããããã䜿çšããããã«ç©ºã®ã¹ãŒããŒã¯ã©ã¹ãäœæããå¿
èŠããããŸãã ãŸããæ§æã¯äžè¬çã«éãããã§ãã ãŸãããã©ã¡ããªãã¯ããã¯ã¹ã€ã³ããµããŒããããŠãããã©ãããæ確ã§ã¯ãããŸããïŒ extends Mixin(Class, { ... })
ãèš±å¯ãããŠããŸãïŒã
çç±ã®ãªã¹ãã«ãã@justinfagnani ããã€ã³ã2ã4ã¯ãå®éã«ã¯TypeScriptã®æ¬ é¥ã§ãããããã¯ã¹ã€ã³ã®å©ç¹ã§ã¯ãããŸããã JSã®äžçã«ã¯é©çšãããŸããã
OPã®åé¡ã«å¯Ÿããããã¯ã¹ã€ã³ããŒã¹ã®ãœãªã¥ãŒã·ã§ã³ã«ã¯ããããã¿ã€ããã§ãŒã³ã«2ã€ã®ã¯ã©ã¹ãè¿œå ããå¿ èŠãããããã®ãã¡ã®1ã€ã¯åœ¹ã«ç«ããªãããšã¯èª°ããæ確ã«ãã¹ãã ãšæããŸãã ããã¯ãããã¯ã¹ã€ã³ãšãã³ã¬ãŒã¿ã®ã»ãã³ãã£ãã¯ã®éããåæ ããŠããŸãããããã¯ã¹ã€ã³ã¯èŠªã¯ã©ã¹ãã§ãŒã³ãã€ã³ã¿ãŒã»ããããæ©äŒãæäŸããŸãã ãããã95ïŒ ã®ç¢ºçã§ãããã¯äººã ãããããããšã§ã¯ãªãããã®ã¯ã©ã¹ã食ããããšæã£ãŠããŸãã ããã¯ã¹ã€ã³ã®çšéã¯éãããŠããŸããããã³ã¬ãŒã¿ãé«æ¬¡ã¯ã©ã¹ã®ä»£ããã«ããã¯ã¹ã€ã³ã宣äŒããããšã¯æå³çã«äžé©åã ãšæããŸãã
ããã¯ã¹ã€ã³ã¯åºæ¬çã«ãã³ã¬ãŒã¿ãšåçã§ããã1ã€ã®å€§ããªåé¡ããããŸã...ã¯ã©ã¹ã«ã¹ãŒããŒã¯ã©ã¹ããŸã ãªãå Žåã¯ããããã䜿çšããããã«ç©ºã®ã¹ãŒããŒã¯ã©ã¹ãäœæããå¿ èŠããããŸã
ããã¯å¿ ãããçå®ã§ã¯ãããŸããïŒ
function Mixin(superclass = Object) { ... }
class Foo extends Mixin() {}
ãŸããæ§æã¯äžè¬çã«éãããã§ãã
ãããã©ããªã£ãŠããã®ãããããªãã®ã§ãæèŠãç°ã«ããå¿ èŠããããŸãã
ãŸãããã©ã¡ããªãã¯ããã¯ã¹ã€ã³ããµããŒããããŠãããã©ãããæ確ã§ã¯ãããŸããïŒMixinïŒClassã{...}ïŒãæ¡åŒµã§ããŸãïŒã
圌ãã¯ãšãŠãããã§ãã ããã¯ã¹ã€ã³ã¯åãªãé¢æ°ã§ãã
çç±ã®ãªã¹ãã§ã¯ããã€ã³ã2ã4ã¯ãå®éã«ã¯TypeScriptã®æ¬ é¥ã§ãããããã¯ã¹ã€ã³ã®å©ç¹ã§ã¯ãããŸããã JSã®äžçã«ã¯é©çšãããŸããã
ããã¯TypeScriptã®åé¡ã§ãããããããã§é©çšãããŸãã JSã®äžçã§ã¯ããã³ã¬ãŒã¿ã¯å®éã«ã¯ãŸã ååšããŠããŸããã
OPã®åé¡ã«å¯Ÿããããã¯ã¹ã€ã³ããŒã¹ã®ãœãªã¥ãŒã·ã§ã³ã«ã¯ããããã¿ã€ããã§ãŒã³ã«2ã€ã®ã¯ã©ã¹ãè¿œå ããå¿ èŠãããããã®ãã¡ã®1ã€ã¯åœ¹ã«ç«ããªãããšã¯èª°ããæ確ã«ãã¹ãã ãšæããŸãã
ã©ãã§2ã€æã«å ¥ãã®ãããããŸããã ããããé©çšããªãéãããã³ã¬ãŒã¿ãšåãããã«1ã€ã§ãã ãããŠãã©ã®ãããã¿ã€ãã圹ã«ç«ããªãã®ã§ããããïŒ ããã¯ã¹ã€ã³ã¢ããªã±ãŒã·ã§ã³ã¯ããããããããã£/ã¡ãœãããè¿œå ããŸãããããã¯åœ¹ã«ç«ããªãããã§ã¯ãããŸããã
ããã¯ãããã¯ã¹ã€ã³ãšãã³ã¬ãŒã¿ã®ã»ãã³ãã£ãã¯ã®éããåæ ããŠããŸãããããã¯ã¹ã€ã³ã¯èŠªã¯ã©ã¹ãã§ãŒã³ãã€ã³ã¿ãŒã»ããããæ©äŒãæäŸããŸãã ãããã95ïŒ ã®ç¢ºçã§ãããã¯äººã ãããããããšã§ã¯ãªãããã®ã¯ã©ã¹ã食ããããšæã£ãŠããŸãã
ãããæ¬åœãã©ããã¯ããããŸããã éåžžãã¯ã©ã¹ãå®çŸ©ãããšãã¯ãã¹ãŒããŒã¯ã©ã¹ã¡ãœããããªãŒããŒã©ã€ãããæ©èœãåãããç¶æ¿éå±€ã®æäžäœã«ããããšãæåŸ
ããŸãã ãã³ã¬ãŒã¿ã¯ã super()
ã§åäœããªããªã©ãå€ãã®åé¡ãããã¯ã©ã¹ã«ããããé©çšããããæ¡åŒµããå¿
èŠããããŸãããã®å Žåãè£
食ãããã¯ã©ã¹ã«ã¯æ¡åŒµããªãŒããŒã©ã€ãããæ©èœããããŸããã ããã¯ãããã©ãŒãã³ã¹/ãããã°ãã¬ãŒã¹ã®ããã«ã¯ã©ã¹ã®å®çŸ©ããããã¹ãŠã®ã¡ãœããããªãŒããŒã©ã€ããããã³ã¬ãŒã¿ã®ããã«ãå Žåã«ãã£ãŠã¯äŸ¿å©ã§ãããéåžžã®ç¶æ¿ã¢ãã«ããã¯ã»ã©é ããã®ã§ãã
ããã¯ã¹ã€ã³ã®çšéã¯éãããŠããŸããããã³ã¬ãŒã¿ãé«æ¬¡ã¯ã©ã¹ã®ä»£ããã«ããã¯ã¹ã€ã³ã宣äŒããããšã¯æå³çã«äžé©åã ãšæããŸãã
éçºè ãããââãã¿ã€ããã§ãŒã³ã«ã¡ã³ããŒãè¿œå ãããå Žåãããã¯ã¹ã€ã³ã¯æ£ç¢ºã«æå³çã«é©åã§ãã 誰ããããã¯ã¹ã€ã³ã«ãã³ã¬ãŒã¿ã䜿çšããããšæã£ãŠããå Žåã¯åžžã«ãã¯ã©ã¹ããã¯ã¹ã€ã³ã䜿çšãããšããã³ã¬ãŒã¿ã«å®éã«æåŸ ããŠããã»ãã³ãã£ã¯ã¹ãã¹ãŒããŒã³ãŒã«ã䜿çšããäœæ¥ããããã£ã«ããæè»æ§ãããã³ãã¡ããã圌ãã¯ä»åããŠããŸãã
Mixinã¯ããŠãŒã¹ã±ãŒã¹ã«çŽæ¥å¯Ÿå¿ããå Žåãã»ãšãã©äžé©åã§ã¯ãããŸããã
éçºè ãããââãã¿ã€ããã§ãŒã³ã«ã¡ã³ããŒãè¿œå ãããå Žå
ããããŸãã«ç§ã®ãã€ã³ãã§ããOPã¯ãããã¿ã€ããã§ãŒã³ã«äœãè¿œå ããããªãã®ã§ãã 圌ã¯ãã 1ã€ã®ã¯ã©ã¹ãå€æŽãããã ãã§ãã»ãšãã©ã®å Žåããã³ã¬ãŒã¿ã䜿çšããå ŽåãObject以å€ã®èŠªã¯ã©ã¹ãããããŸããã ãŸããäœããã®çç±Mixin(Object)
ã¯TypeScriptã§æ©èœããªãããããããŒã®ç©ºã®ã¯ã©ã¹ãè¿œå ããå¿
èŠããããŸãã ããã§ãäžèŠãªãšãã«2ã€ã®ãããã¿ã€ããã§ãŒã³ïŒãªããžã§ã¯ããå«ãŸãªãïŒãã§ããŸããã ããã«ããããã¿ã€ããã§ãŒã³ã«æ°ããã¯ã©ã¹ãè¿œå ããã«ã¯ãåãã«è¶³ããªãã³ã¹ããããããŸãã
æ§æã«ã€ããŠã¯ã Mixin1(Mixin2(Mixin3(Object, { ... }), {... }), {...})
ãæ¯èŒããŠãã ããã åããã¯ã¹ã€ã³ã®ãã©ã¡ãŒã¿ãŒã¯ãããã¯ã¹ã€ã³ã¯ã©ã¹ããå¯èœãªéãé¢ããŠããŸãã ãã³ã¬ãŒã¿æ§æã¯æããã«ããèªã¿ããããªã£ãŠããŸãã
ãã³ã¬ãŒã¿æ§æèªäœã¯ã¿ã€ããã§ãã¯ãè¡ããŸããããéåžžã®é¢æ°åŒã³åºãã䜿çšããŠãå¿ èŠãªãã®ãååŸã§ããŸãã
class Logger { static instance() { return new Logger(); } }
type Loggable<T> = T & { logger: Logger };
function loggable<T, U>(target: { new (): T } & U): { new (): Loggable<T> } & U
{
// ...
}
const Foo = loggable(class {
x: string
});
let foo = new Foo();
foo.logger; // Logger
foo.x; // string
ã¯ã©ã¹ãconst Foo = loggable(class {
ãšããŠå®£èšããªããã°ãªããªãã®ã¯å°ãé¢åã§ããããã以å€ã¯ãã¹ãŠæ©èœããŸãã
@ohjames ïŒcc @justinfagnaniïŒ Object
ãªã©ã®ãã«ãã€ã³ãæ¡åŒµããå Žåã¯æ³šæãå¿
èŠã§ãïŒã€ã³ã¹ã¿ã³ã¹ã§ãµãã¯ã©ã¹ã®ãããã¿ã€ããããã·ã¥ããããïŒïŒ https ïŒ//github.com/Microsoft/TypeScript/wiki/FAQ
@nevirãããç§ã¯ãã§ã«TypeScript 2.2ã§ããã©ã«ãã®Object
ãã©ã¡ãŒã¿ã§ããã¯ã¹ã€ã³ã䜿çšãããšãã@justinfagnaniã®ææ¡ãè©ŠããŸããããtscã¯ã³ãŒããæåŠããŸãã
@ohjamesã¯åŒãç¶ãæ©èœããŸããããã©ã«ãã®å Žåã®ãããã¿ã€ãã«æ³šæããå¿ èŠããããŸãïŒFAQãšã³ããªãåç §ïŒã
ãã ããäžè¬çã«ã null
ãæž¡ãããšãã®tslib.__extend
ã®åäœã«äŸåããæ¹ãç°¡åã§ãã
次ã®å埩ã¹ãããã§ãã®åé¡ã«çŠç¹ãåœãŠãèšç»ã¯ãããŸããïŒ ãã®æ©èœã®å©ç¹ã¯ãéåžžã«å€ãã®ã©ã€ãã©ãªã§éåžžã«é«ãããšã§ãã
ç§ã¯ã¡ããã©ãã®åé¡ã«ééããŸãã-ããã¯ç§ã«å€ãã®äžå¿ èŠãªã³ãŒããæžãããšã匷å¶ããŸãã ãã®åé¡ã解決ããããšã¯ããã³ã¬ãŒã¿ããŒã¹ã®ãã¬ãŒã ã¯ãŒã¯/ã©ã€ãã©ãªã«ãšã£ãŠå€§ããªå©ãã«ãªããŸãã
@TomMariusåè¿°ããããã«ããã³ã¬ãŒã¿é¢æ°ã§ã©ãããããã¯ã©ã¹ã¯ãã§ã«æ£ããåãã§ãã¯ãããŠããããã @
æ§æã®ç³è¡£ã䜿çšããããšã¯ã§ããŸããã è¡ã代ããã«ïŒ
<strong i="8">@loggable</strong>
class Foo { }
ããªãã¯ãã ããå¿ èŠããããŸãïŒ
const Foo = loggable(class { });
ã¯ã©ã¹ãã©ããããåã«ãäžé£ã®ãã³ã¬ãŒã¿é¢æ°ãäžç·ã«äœæããããšãã§ããŸãã ã·ã³ã¿ãã¯ã¹ã·ã¥ã¬ãŒãé©åã«æ©èœãããããšã¯äŸ¡å€ããããŸããããããããã»ã©å€§ããªåé¡ã«ãªããšã¯æããŸããã
@masaeeduæ¬åœã«åé¡ã¯å€éšã§ã¯ãªããå
éšã¿ã€ãã®ãµããŒãã§ãã ãã³ã¬ãŒã¿ãã¯ã©ã¹èªäœã«è¿œå ããããããã£ãã³ã³ãã€ã«ãšã©ãŒãªãã§äœ¿çšã§ããããšã¯ãå°ãªããšãç§ã«ãšã£ãŠã¯æãŸããçµæã§ãã ããªããæäŸããäŸã¯ã Foo
ã«ãã°å¯èœãªåãäžããã ãã§ãã¯ã©ã¹å®çŸ©èªäœã«ãã®åãäžããããšã¯ã§ããŸããã
@zajrikçµã¿èŸŒã¿ã®@
æ§æã䜿çšããŠããå Žåã§ãããã³ã¬ãŒã¿ã¯å
ã®ã¯ã©ã¹ããæ°ããã¯ã©ã¹ãè¿ããŸãã æããã«JSã¯çŽç²ãã匷å¶ããªãã®ã§ãæž¡ãããå
ã®ã¯ã©ã¹ãèªç±ã«å€æŽã§ããŸãããããã¯ãã³ã¬ãŒã¿ã®æŠå¿µã®æ
£çšçãªäœ¿çšæ³ãšäžèŽããŸããã ãã³ã¬ãŒã¿ãä»ããŠã¯ã©ã¹å
éšã«è¿œå ããæ©èœãç·å¯ã«çµåããŠããå Žåããããã¯å
éšããããã£ã§ããå¯èœæ§ããããŸãã
åŸã§ãã³ã¬ãŒã¿ãä»ããŠè¿œå ããããå éšã§æ¶è²»ããAPIã®ã¯ã©ã¹ã®ãŠãŒã¹ã±ãŒã¹ã®äŸãæããŠãã ããã
äžèšã®ãã¬ãŒã®äŸã¯ãè£ é£Ÿãããã¯ã©ã¹ã®å éšãæäœã§ããããã«ããããã®äžè¬çãª_want_ã®è¯ãäŸã§ãã ïŒãããŠãPythonãªã©ã®ã¯ã©ã¹è£ 食ãåããä»ã®èšèªããæ¥ã人ã ã«ã¯ãªãã¿ããããŸãïŒ
ããã¯èšã£ãŠãã @ justinfagnaniã®ã¯ã©ã¹ããã¯ã¹ã€ã³ã®ææ¡ã¯ãã®å Žåã®è¯ã代æ¿æ¡ã®ããã§ã
ã¯ã©ã¹ã®å éšãå®çŸ©ã§ããããã«ãããå Žåããããè¡ãããã®æ§é åãããæ¹æ³ã¯ãã¯ã©ã¹ã«ããããé©çšããããæ°ãããµãã¯ã©ã¹ãå®çŸ©ãããããããšã§ã¯ãããŸãããã©ã¡ãããTypeScriptãã¯ã©ã¹ã®ã³ã³ããã¹ãã§æšè«ããã®ã«èŠåŽããŸããããèªäœã§ãããã¯ã©ã¹èªäœã§ç©äºãå®çŸ©ããããTypeScriptãæšè«ã§ããå¿ èŠãªããããã£ãæã€æ°ããã¹ãŒããŒã¯ã©ã¹ãäœæããŸãã
ãã³ã¬ãŒã¿ã¯ãå®éã«ã¯ãã¯ã©ã¹ãŸãã¯ã»ãšãã©ã®ã³ã³ã·ã¥ãŒããŒã«è¡šç€ºãããæ¹æ³ã§ã¯ã©ã¹ã®åœ¢ç¶ãå€æŽããã¹ãã§ã¯ãããŸããã @masaeeduã¯ããã«ãããŸãã
ããªããèšã£ãŠããããšã¯çå®ã§ãããTypeScriptã¯ã¯ãªãŒã³ãªã³ãŒãã£ã³ã°æ £è¡ã匷å¶ããããã§ã¯ãªããJavaScriptã³ãŒããæ£ããå ¥åããããã®ãã®ã§ããããã®å Žåã¯å€±æããŸãã
@ masaeedu @ zajrikãèšã£ãããšã ã¯ã©ã¹ã§äœ¿çšãããäžé£ã®ããããã£ãã¯ã©ã¹ã«è¿œå ããããªã³ã©ã€ã³ãµãŒãã¹ãã宣èšãããã³ã¬ãŒã¿ããããŸãã ã¡ã¿ããŒã¿ãšå¶çŽã®é©çšãæ¬ èœããŠããããïŒã³ãŒãã®éè€ããªãããã«åªããŠããå ŽåïŒãã€ã³ã¿ãŒãã§ã€ã¹ã®ãµãã¯ã©ã¹åãŸãã¯å®è£ ã¯ãªãã·ã§ã³ã§ã¯ãããŸããã
@TomMariusç§ã®ãã€ã³ãã¯ããããæ£ããåãã§ãã¯ããŠãããšããããšã§ãã ãã³ã¬ãŒã¿é¢æ°ãã¯ã©ã¹ã«é©çšããŠããã¯ã©ã¹ã¯ãŸã£ããå€æŽãããŸããã æ°ããã¯ã©ã¹ã¯ãå ã®ã¯ã©ã¹ã®å€æã«ãã£ãŠçæããããã®æ°ããã¯ã©ã¹ã®ã¿ãããã³ã¬ãŒã¿é¢æ°ã«ãã£ãŠå°å ¥ãããAPIããµããŒãããããšãä¿èšŒãããŠããŸãã
ãã¡ã¿ããŒã¿ãšå¶çŽã®åŒ·å¶ããªãããšã¯ã©ãããæå³ãããããŸãããïŒå
·äœçãªäŸã圹ç«ã€ãããããŸããïŒãã¯ã©ã¹ããã³ã¬ãŒã¿ã«ãã£ãŠå°å
¥ãããAPIã«æ瀺çã«äŸåããŠããå Žåã¯ã @ justinfagnaniã瀺ããããã¯ã¹ã€ã³ãã¿ãŒã³ãä»ããŠçŽæ¥ãµãã¯ã©ã¹åããå¿
èŠããããŸãããŸãã¯ã³ã³ã¹ãã©ã¯ã¿ãªã©ãä»ããŠæ³šå
¥ããŸãã ãã³ã¬ãŒã¿ã®æçšæ§ã¯ãå€æŽãå¯èœãªã¯ã©ã¹ãæ¡åŒµããŠããããã®ã¯ã©ã¹ãæ¶è²»ããã³ãŒãã®å©çãåŸãããšãã§ããããšã§ãã ã¯ã©ã¹ãèªåã§èªç±ã«å®çŸ©ã§ããå Žåã¯ã extends
ã䜿çšããŠãã ããã
@masaeeduããçš®ã®ãããšãã°RPCã©ã€ãã©ãªãéçºããŠããŠããŠãŒã¶ãŒã«éåæã¡ãœããã®ã¿ãèšè¿°ããããå Žåãç¶æ¿ããŒã¹ã®ã¢ãããŒãã§ã¯ã³ãŒããè€è£œããå¿ èŠããããŸãïŒãŸãã¯æ£ããæ¹æ³ãèŠã€ãããŸããã§ããïŒ ãå€å-æ¹æ³ãç¥ã£ãŠããã°æããŠããã ããã°å¹žãã§ãïŒã
éºäŒããŒã¹ã®ã¢ãããŒã
å®çŸ©ïŒ export abstract class Service<T extends { [P in keyof T]: () => Promise<IResult>}> { protected someMethod(): Promise<void> { return Promise.reject(""); } }
䜿çšæ³ïŒ export default class MyService extends Service<MyService> { async foo() { return this.someMethod(); } }
ãã³ã¬ãŒã¿ããŒã¹ã®ã¢ãããŒã
å®çŸ©ïŒ export function service<T>(target: { new (): T & { [P in keyof T]: () => Promise<IResult> } }) { target.someMethod = function () { return Promise.reject(""); }; return target; }
䜿çšæ³ïŒ <strong i="17">@service</strong> export default class { async foo() { return this.someMethod(); } }
ç¶æ¿ããŒã¹ã®ã¢ãããŒãã®äŸã§ã¯ãã³ãŒãã®éè€ãæ確ã«ç¢ºèªã§ããŸãã ã¯ã©ã¹ãã³ããŒããŠè²Œãä»ãããšãããŸãã¯ã¿ã€ããã©ã¡ãŒã¿ãšããŠãanyãã䜿çšãå§ãããšãã«ã¿ã€ããã©ã¡ãŒã¿ãå€æŽããã®ãå¿ããŠãã©ã€ãã©ãªãæ©èœããªããªã£ãããšããç§ãšãŠãŒã¶ãŒã«äœåºŠãèµ·ãããŸããã ãã³ã¬ãŒã¿ããŒã¹ã®ã¢ãããŒãã¯ãéçºè ã«ãšã£ãŠã¯ããã«äœ¿ãããããã®ã§ãã
ãã®åŸãç¶æ¿ããŒã¹ã®ã¢ãããŒãã«ã¯ããã«å¥ã®åé¡ããããŸãããªãã¬ã¯ã·ã§ã³ã¡ã¿ããŒã¿ãæ¬ èœããŠããããããšã«ããservice
ãã³ã¬ãŒã¿ãå°å
¥ããå¿
èŠããããããã³ãŒããããã«è€è£œããå¿
èŠããããŸãã çŸåšã®äœ¿çšæ³ã¯<strong i="22">@service</strong> export default class MyService extends Service<MyService> { async foo() { return this.someMethod(); } }
ã§ããããã¯ãå°ãäžäŸ¿ãªã ãã§ãªãããŸã£ããäžèŠªåã§ãã
ã¯ã©ã¹ãå®çŸ©ãããåŸã«æå³çã«å€æŽãè¡ãããã®ã¯äºå®ã§ãããè£ é£ŸãããŠããªãã¯ã©ã¹ãã€ã³ã¹ã¿ã³ã¹åããæ¹æ³ã¯ãªããããã¯ã©ã¹ã®å€æŽãé©åã«ãµããŒãããªãçç±ã¯ãããŸãããããè¯ãåã®ããã«ïŒã JavaScriptã¯ãŸã ãããã¿ã€ãã«åºã¥ããŠããããšãå¿ããªãã§ãã ãããã¯ã©ã¹ã®æ§æã¯ããããã«ããŒããããã®åãªãç ç³ã§ãã ãããã¿ã€ãã¯å€æŽå¯èœã§ããããã³ã¬ãŒã¿ã«ãã£ãŠãã¥ãŒããããå¯èœæ§ããããããæ£ããå ¥åããå¿ èŠããããŸãã
ãã³ã¬ãŒã¿é¢æ°ãã¯ã©ã¹ã«é©çšããŠããã¯ã©ã¹ã¯ãŸã£ããå€æŽãããŸããã
ããã§ã¯ãããŸããããã³ã¬ãŒã¿é¢æ°ãã¯ã©ã¹ã«é©çšãããšãã¯ã©ã¹ãå€æŽãããå¯èœæ§ããããŸãã 奜ããã©ããã
@TomMariusæšè«ãå©çšããŠå¥çŽã匷å¶ããããšããŠããŸãããããã¯ããã§ã®è°è«ãšã¯ãŸã£ããé¢ä¿ãããŸããã ããªãã¯ãã ããã¹ãã§ãïŒ
function service<T>(target: { new (): T & {[P in keyof T]: () => Promise<any> } }) { return target };
// Does not type check
const MyWrongService = service(class {
foo() { return ""; }
})
// Type checks
const MyRightService = service(class {
async foo() { return ""; }
})
ã¯ã©ã¹ã®å éšãè£ é£Ÿæ©èœãèªèããå¿ èŠã¯ãŸã£ãããããŸããã
@masaeeduããã¯ç§ã®ãã€ã³ãã§ã¯ãããŸããã§ããã ãµãŒãã¹ãã³ã¬ãŒã¿/ãµãŒãã¹ã¯ã©ã¹ã¯ããã€ãã®æ°ããããããã£ãå°å ¥ãããããã¯äœ¿çšãããã¯ã©ã¹ã§åžžã«å©çšå¯èœã§ãããåã·ã¹ãã ã¯ãããæ£ããåæ ããŠããŸããã ããªãã¯ç§ããã®ããã«ç¶æ¿ã䜿ãã¹ãã ãšèšã£ãã®ã§ãç§ãããããããšãã§ããªã/ããããªãçç±ãããªãã«ç€ºããŸããã
ããæ確ã«ãªãããã«äŸãç·šéããŸããã
@masaeeduã¡ãªã¿ã«ãããã³ã¬ãŒã¿ã¯å ã®ã¯ã©ã¹ããæ°ããã¯ã©ã¹ãè¿ãããšããèšè¿°ã¯æ£ãããããŸãããããã§ç€ºãããã¹ãŠã®ãã³ã¬ãŒã¿ã¯ãå€æŽãããã¯ã©ã¹ãŸãã¯çŽæ¥å ã®ã¯ã©ã¹ãè¿ããŸãããæ°ããã¯ã©ã¹ã¯è¿ããŸããã
@TomMariusããªãã®ã³ã¡ã³ãã¯ãããŠãŒã¶ãŒã«éåæã¡ãœããã®ã¿ãèšè¿°ãããããšããåé¡ã«ã€ããŠèšåããŠããŸãããããã¯ãç§ãã³ã¡ã³ãã§å¯ŸåŠããããšããåé¡ã§ãã ãŠãŒã¶ãŒãæåŸ ããã³ã³ãã©ã¯ãã«åŸã£ãŠããããšã匷å¶ããããšã¯ããŠãŒã¶ãŒã®ã³ãŒããã©ã€ãã©ãªã«è¿ãããå Žåã¯åžžã«è¡ãå¿ èŠãããããã³ã¬ãŒã¿ãã¯ã©ã¹å éšã«æ瀺ãããåã®åœ¢ãå€æŽããå¿ èŠããããã©ããã«ã€ããŠã®è°è«ãšã¯é¢ä¿ãããŸããã ãŠãŒã¶ãŒã®ã³ãŒãã«APIãæäŸãããšããçŽäº€ããåé¡ã¯ãæšæºã®ç¶æ¿ãŸãã¯æ§æã¢ãããŒãã§è§£æ±ºã§ããŸãã
@ohjamesãã³ã¬ãŒã¿ãé©çšããã ãã§ã¯ãã¯ã©ã¹ã¯å€æŽãããŸããã JSã¯çŽç²ãã匷å¶ããªããããã³ãŒãå ã®ä»»æã®ã¹ããŒãã¡ã³ãã§ä»ã®ã¹ããŒãã¡ã³ããå€æŽã§ããããšã¯æããã§ãããããã¯ãã®æ©èœã®èª¬æãšã¯ç¡é¢ä¿ã§ãã æ©èœãå®è£ ãããåŸã§ããTypeScriptã¯é¢æ°æ¬äœå ã®ä»»æã®æ§é å€æŽã远跡ããã®ã«åœ¹ç«ã¡ãŸããã
@masaeeduããªãã¯ããããéžãã§ããŸãããç§ã¯å šäœåã«ã€ããŠè©±ããŠããã®ã§ãã ãã®ã¹ã¬ããã®ç§ã®ã³ã¡ã³ãããã¹ãŠç¢ºèªããŠãã ãããèŠç¹ã¯åã ã®åé¡ã§ã¯ãªããåæã«çºçããååé¡ã«ãããŸãã ç¶æ¿ããŒã¹ã®ã¢ãããŒãã®åé¡ãããŸã説æãããšæããŸã-ããããã®ã³ãŒãã®éè€ã
æ確ã«ããããã«ãããã¯ç§ã«ãšã£ãŠãã¯ãªãŒã³ãªã³ãŒããã«ã€ããŠã§ã¯ãããŸããã åé¡ã¯å®çšæ§ã®1ã€ã§ãã @foo
ãé¢æ°é©çšãšåãããã«æ±ãå Žåã¯ãåã·ã¹ãã ã«å€§å¹
ãªå€æŽãå ããå¿
èŠã¯ãããŸããã åæ
å ±ããã®æ»ãåããé¢æ°ã®åŒæ°ã«å°å
¥ããããšããã¯ãŒã ã®çŒ¶ãéãããšãåæã«åæšè«ãTypeScriptåã·ã¹ãã ã®ããŸããŸãªã³ãŒããŒã§èŠã€ãã£ãä»ã®ãã¹ãŠã®éæ³ã®ç£ãšçžäºäœçšããŸããããã¯ãçŸåšã®ãªãŒããŒããŒããšã»ãŒåãããã«ãæ°æ©èœã®å€§ããªé害ã«ãªããŸãã
@TomMariusãã®ã¹ã¬ããã§ã®æåã®ã³ã¡ã³ãã¯ãé¢é£æ§ã®ãªãã¯ãªãŒã³ãªã³ãŒãã«é¢ãããã®ã§ãã 次ã®ã³ã¡ã³ãã¯ããµã³ãã«ã³ãŒããæäŸãããã®ãªã³ã©ã€ã³ãµãŒãã¹ã®æŠå¿µã«ã€ããŠã§ãã æåã®æ®µèœãã4çªç®ã®æ®µèœãŸã§ã®äž»ãªäžæºã¯ã MyService extends Service<MyService>
ã䜿çšãããšãšã©ãŒãçºçããããããšã§ãã ããã«å¯ŸåŠããæ¹æ³ã®äŸã瀺ããŠã¿ãŸããã
ããäžåºŠèŠãŠã¿ãŸãããããã®äŸã§ã¯ããã³ã¬ãŒããããã¯ã©ã¹ã®ã¡ã³ããŒããã³ã¬ãŒã¿ãèªèããå¿ èŠãããçç±ã瀺ããã®ã¯å®éã«ã¯äœãããããŸããã æšæºã®ç¶æ¿ã§ã¯å®çŸã§ããªãããŠãŒã¶ãŒã«æäŸãããããã®æ°ããããããã£ã«ã€ããŠã¯ã©ãã§ããããã ç§ã¯ãªãã¬ã¯ã·ã§ã³ã䜿ã£ãããšããªãã®ã§ãããããã£ãšèŠãã ãã§ããè©«ã³ããŸãã
@masaeeduç¶æ¿ã§ãããéæããããšã¯ã§ããŸãããç¶æ¿ã«ãã£ãŠç§/ç§ã®ãŠãŒã¶ãŒã¯ã³ãŒãã倧éã«è€è£œããå¿ èŠãããã®ã§ãå¥ã®æ¹æ³ãå¿ èŠã§ã-ãããŠç§ã¯ããããŸãããåã·ã¹ãã ã¯çŸå®ãæ£ããåæ ã§ããŸããã
éèŠãªã®ã¯ã service
ã<T>(target: T) => T & IService
ãšããŠå®£èšãããŠããæ£ããã¿ã€ãã®<strong i="7">@service</strong> class X { }
ã¯ã X
ã§ã¯ãªãã X & IService
ã§ãã åé¡ã¯ãå®éã«ã¯ãæå³çã«ã¯æ£ãããªãå Žåã§ããã¯ã©ã¹å
ã§ãåœãŠã¯ãŸããšããããšã§ãã
ãã®åé¡ãåŒãèµ·ãããã1ã€ã®å€§ããªåé¡ã¯ãããããã«å¶çŽãããäžé£ã®ãã³ã¬ãŒã¿ãããå Žåãåã·ã¹ãã ã¯ã¿ãŒã²ãããåžžã«å ã®ã¯ã©ã¹ã§ãããè£ é£Ÿãããã¯ã©ã¹ã§ã¯ãªããšèŠãªããããå¶çŽã圹ã«ç«ããªãããšã§ãã
ç¶æ¿ã§ãããéæããããšã¯ã§ããŸãããç¶æ¿ã«ãã£ãŠç§/ç§ã®ãŠãŒã¶ãŒã¯ã³ãŒãã倧éã«è€è£œããå¿ èŠãããã®ã§ãå¥ã®æ¹æ³ãå¿ èŠã§ãã
ããã¯ç§ãç解ããŠããªãéšåã§ãã ãŠãŒã¶ãŒã¯IService
ãå®è£
ããå¿
èŠãããã TheirService implements IService
ãä»ã®å¥çŽ{ [P in keyof blablablah] }
ã«ãæºæ ããŠããããšã確èªãããããããŠãŒã¶ãŒã«ã{ potato: Potato }
ãæãããããšèããŠããŸãã圌ãã®ãµãŒãã¹ã«ã ããã¯ãã¹ãŠãã¯ã©ã¹ã®ã¡ã³ããŒã@service
ãæèããŠããªããŠãç°¡åã«å®è¡ã§ããŸãã
import { serviceDecorator, BaseService } from 'library';
// Right now
const MyService = serviceDecorator(class extends BaseService {
async foo(): { return ""; }
})
const MyBrokenService1 = serviceDecorator(class extends BaseService {
foo(): { return; } // Whoops, forgot async! Not assignable
});
const MyBrokenService2 = serviceDecorator(class { // Whoops, forgot to extend BaseService! Not assignable
async foo(): { return; }
});
// Once #4881 lands
<strong i="13">@serviceDecorator</strong>
class MyService extends BaseService {
async foo(): { return ""; }
}
ã©ã¡ãã®å Žåãã$ïŒ$ 7 $ïŒ$ã®ã¿ã€ããšããŠthis
ã®ãªã¿ãŒã³ã¿ã€ããserviceDecorator
foo
æ瀺ããããšã«ãã£ãŠã®ã¿éæã§ãããç°¡æœãã®å€§ããªåå©ã¯ãããŸããã ããã«éèŠãªããšã¯ããã®ããã®ããå¥å
šãªã¿ã€ãã³ã°æŠç¥ãã©ã®ããã«èãåºãããšãææ¡ããã®ã§ããããã serviceDecorator
ã®æ»ãåã¯ãè£
食ããŠããã¯ã©ã¹ã®åã«åºã¥ããŠæšæž¬ããããã³ã¬ãŒã¿ã®æ»ãåãšããŠå
¥åãããŸã...
ããã«ã¡ã¯@masaeedu ãããªããè€æ°ãæã£ãŠãããšããç°¡æœãã¯ç¹ã«äŸ¡å€ããããŸãã
@Component({ /** component args **/})
@Authorized({/** roles **/)
<strong i="7">@HasUndoContext</strong>
class MyComponent {
// do stuff with undo context, component methods etc
}
ãã ãããã®åé¿çã¯ã¯ã©ã¹ãã³ã¬ãŒã¿ã®ä»£æ¿æ段ã«ãããŸããã ã¡ãœãããã³ã¬ãŒã¿ã®å ŽåãçŸåšã®ãšãã解決çã¯ãªããéåžžã«åªããå®è£ ããããã¯ããŠããŸãã ãã³ã¬ãŒã¿ã¯ã¹ããŒãž2ã§ææ¡ãããŠããŸã-httpsïŒ//github.com/tc39/proposal-decorators ã ãã ããå®è£ ãããªãæ©ãè¡ãããå Žåãå€ããããŸããã ç¹ã«ãã³ã¬ãŒã¿ã¯ãéåžžã«å€ãã®ãã¬ãŒã ã¯ãŒã¯ã§ãã§ã«äœ¿çšãããŠãããéåžžã«åçŽãªããŒãžã§ã³ããã§ã«babel / tsã«å®è£ ãããŠãããããéåžžã«éèŠãªéèŠãªããªãã¯ã®1ã€ã ãšæããŸãã ãã®åé¡ãå®è£ ã§ããã°ãå ¬åŒãªãªãŒã¹ãŸã§å®éšçãªç¶æ ã倱ãããšã¯ãããŸããã ããããããã¯ã®ãå®éšçãã§ãã
@pietschyã¯ãã @
æ§æã®ç³è¡£æ§æãåãã§ãã¯ã§é©åã«æ©èœããããšäŸ¿å©ã§ãã çŸæç¹ã§ã¯ãé¢æ°åæã䜿çšããŠãé©åºŠã«é¡äŒŒããç°¡æœããåŸãããšãã§ããŸãã
const decorator = compose(
Component({ /** component args **/ }),
Authorized({ /** roles **/ })
HasUndoContext
);
const MyComponent = decorator(class {
});
ãããŸã§ã®èª¬æã¯ããã³ã¬ãŒã¿ã®æ»ãåãã¯ã©ã¹ã®ã¡ã³ããŒã«this
ã®åãšããŠæ瀺ããããããçš®ã®éåä»ããè¡ãã®ãè¯ãèããã©ããã«ã€ããŠã§ãã
ããã«ã¡ã¯@masaeedu ããããç§ã¯è°è«ã®æèãç解ããã®ã§ã // do stuff with undo context, component methods etc
ã 也æ¯
Mixinsããã£ãšç°¡åã«ããå¿ èŠããããŸãã
typescriptïŒjavascriptïŒã¯å€éç¶æ¿ããµããŒãããŠããªããããMixinsãŸãã¯Traitsã䜿çšããå¿
èŠããããŸãã
ãããŠä»ãç¹ã«ç§ãäœããåæ§ç¯ãããšããããã¯ç§ã«å€ãã®æéã浪費ããŠããŸãã
ãããŠãã空ã®å®è£
ããåããã€ã³ã¿ãŒãã§ãŒã¹ãã©ãã«ã§ãã³ããŒããŠè²Œãä»ããå¿
èŠããããŸãã ïŒïŒ371ïŒ
-
ãªã¿ãŒã³ã¿ã€ãã®ãã³ã¬ãŒã¿ãã¯ã©ã¹ã§æ瀺ããã¹ãã§ã¯ãªããšæããŸãã
çç±ïŒ....ãšã ã ããã説æããæ¹æ³ãããããªããç§ã®è²§åŒ±ãªè±èªã¹ãã«ããè©«ã³ããŸã...ïŒð€ãã©ããã¬ãŒã ãªãã§åçãååšããããšã¯ã§ããŸããïŒïŒãã®ä»äºã¯interface
ã§ãã
ããã«ç§ã®+1ãè¿œå ããŸãïŒ ç§ã¯ãããããã«æ¥ãã®ãèŠããã§ãã
@pietschyã¯ã©ã¹ããã³ã¬ãŒã¿ã«ãã£ãŠè¿œå ãããã¡ã³ããŒã«äŸåããŠããå Žåããã®éã§ã¯ãªãããã³ã¬ãŒã¿ã®çµæãæ¡åŒµããå¿ èŠããããŸãã ãã£ãã»ããããïŒ
const decorator = compose(
Component({ /** component args **/ }),
Authorized({ /** roles **/ })
HasUndoContext
);
class MyComponent extends decorator(class { }) {
// do stuff with undo context, component methods etc
};
å¥ã®æ¹æ³ã¯ãåã·ã¹ãã ãäœããã®ã«ãŒãã§æ©èœããããšã§ããããã§ããã³ã¬ãŒã¿é¢æ°ã®åŒæ°ã¯ããã®åŒæ°ããæšæž¬ãããæ»ãåã«ãã£ãŠæèçã«åä»ãããããã®åŒæ°ã¯ããã®æ»ãåãªã©ã«ãã£ãŠæèçã«åä»ããããŸãããããã©ã®ããã«æ©èœãããã«ã€ããŠã®å ·äœçãªææ¡ã¯ãå®è£ ãåŸ ã£ãŠããã ãã§ã¯ãããŸããã
ããã«ã¡ã¯@masaeedu ããã³ã¬ãŒã¿ãäœæããŠãããåºæ¬ã¯ã©ã¹ã«é©çšããå¿ èŠãããçç±ã«ã€ããŠæ··ä¹±ããŠããŸãã ç§ãç解ããŠããéãããããã¿ã€ãã¯ããŠãŒã¶ãŒã®åå°ã³ãŒããå®è¡ããããŸã§ã«ãã§ã«å€æŽãããŠããŸãã äŸãã°
function pressable<T extends {new(...args:any[]):{}}>(constructor:T) {
return class extends constructor {
pressMe() {
console.log('how depressing');
}
}
}
<strong i="7">@pressable</strong>
class UserLandClass {
constructor() {
this['pressMe'](); // this method exists, please let me use code completion.
}
}
console.log(new UserLandClass());
ãããã£ãŠããã³ã¬ãŒã¿ã«ãã£ãŠå®çŸ©ãããã¡ãœããããã§ã«ååšããåæ³çã«åŒã³åºãããšãã§ããå Žåã¯ãtypescriptããããåæ ããŠãããšäŸ¿å©ã§ãã
ã¿ã€ãã¹ã¯ãªãããåé¿çã課ãããšãªããããåæ ããããšãæãŸããŸãã ä»ã«ããå Žå
ãã³ã¬ãŒã¿ãå®è¡ã§ããããšãã¢ãã«åã§ããªãå Žåã¯ãå°ãªããšããããããã°ããã§ããã
ã·ããªãªã¯ãäœããã®åœ¢ãŸãã¯åœ¢åŒã§ãµããŒããããŠããŸããã
ãã®ã¹ã¬ããã¯ããã³ã¬ãŒã¿ãäœããã¹ãããã©ã®ããã«äœ¿çšãããã¹ãããã©ã®ããã«äœ¿çšãããã¹ãã§ãªãããªã©ã«ã€ããŠã®æèŠã§ãã£ã±ãã§ãã
ããã¯ããã³ã¬ãŒã¿ãå®éã«è¡ãããšã§ãã
function addMethod(Class) : any {
return class extends Class {
hello(){}
};
}
<strong i="13">@addMethod</strong>
class Foo{
originalMethod(){}
}
ããã¯ãesnextãã¿ãŒã²ããã«ããŠããå Žåã«ãªããŸã
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
function addMethod(Class) {
return class extends Class {
hello() {
}
};
}
let Foo = class Foo {
originalMethod() { }
};
Foo = __decorate([
addMethod
], Foo);
__decorate
ãåãã³ã¬ãŒã¿ãäžããäžã«é©çšããåãã³ã¬ãŒã¿ã«ã¯ãŸã£ããæ°ããã¯ã©ã¹ãè¿ããªãã·ã§ã³ããããŸãã
åã·ã¹ãã ã«ããããµããŒããããããšã¯éåžžã«é£ãããããããŸããããããããµããŒãããã«ã¯æéãããããããããªãããšãç解ããŠããŸããããããéå§ããäžèšã®å ã®ã³ãŒããµã³ãã«ããã®çŸåšã®åäœã«åæããããšã¯ã§ããŸããã¹ã¬ãããåã«ééã£ãŠããŸããïŒ
ãã³ã¬ãŒã¿ãããã¯ã¹ã€ã³ãæ©èœæ§æãªã©ã«é¢ããéçºè ã®æèŠãäœã§ãããããã¯ããªãæãããªãã°ã®ããã§ãã
ãããå°æ¥ã®ãªãªãŒã¹ã®ãã€ãã©ã€ã³ã«ãããã©ããã«ã€ããŠäžå¯§ã«åãåãããããšã¯ã§ããŸããïŒ
TypeScriptã¯åçŽã«çŽ æŽããããç§ã¯ããã倧奜ãã§ãã ããããããã¯åã«å£ããŠããæ°å°ãªãïŒå¯äžã®ïŒïŒéšåã®1ã€ã®ããã«æããŸãããããŠç§ã¯ãããä¿®æ£ãããã®ãèŠãã®ã楜ãã¿ã«ããŠããŸã:)
@arackafãã³ã¬ãŒã¿ãå®éã«äœããããã¯ããç解ãããŠãããTypeScriptã®emitããã§ã«ãã³ã¬ãŒã¿ããµããŒãããŠããã¿ã€ããæ°ã«ããªããšä»®å®ããŸãã ãã®åé¡ã®å šäœçãªè°è«ã¯ãè£ é£Ÿãããã¯ã©ã¹ãåã·ã¹ãã ã§ã©ã®ããã«æ瀺ãããã¹ããã«ã€ããŠã§ãã
new Foo().foo
ãåãšã©ãŒã§ããããšã¯ãã°ã§ãããç°¡åã«ä¿®æ£ã§ããããšã«åæããŸãã return this.foo;
ãã¿ã€ããšã©ãŒã§ããããšããã°ã§ããããšã«åæããŸããã ã©ã¡ãããšããã°ããããŸã§ãã®åé¡ã®èª°ããŸã æå®ããŠããªãåã·ã¹ãã ã®æ©èœãæ±ããŠããŸãã this
ã®ã¿ã€ããããããå«ãã¯ã©ã¹ã«é©çšããããã³ã¬ãŒã¿ã«ãã£ãŠå€æãããã¡ã«ããºã ã念é ã«çœ®ããŠããå Žåã¯ããã®ã¡ã«ããºã ãæ瀺çã«ææ¡ããå¿
èŠããããŸãã
ã»ãšãã©ãã¹ãŠã®å Žåããã³ã¬ãŒã¿ã®ãªã¿ãŒã³ã¿ã€ãã¯ããã³ã¬ãŒã¿ã®ãªã¿ãŒã³ã¿ã€ãã䜿çšããŠå€æããããšãææ¡ããŠããã¿ã€ãããæšæž¬ãããããããã®ãããªã¡ã«ããºã ã¯æåŸ
ããã»ã©ç°¡åã§ã¯ãããŸããã ãã³ã¬ãŒã¿addMethod
ãã¿ã€ãnew () => T
ã®ã¯ã©ã¹ãåãã new() => T & { hello(): void }
ãçæããå Žåã T
ãT & { hello(): void }
ã«ããããšãææ¡ããã®ã¯æå³ããããŸããã super.hello
ãåç
§ããããšã¯æå¹ã§ããïŒ
ããã¯ããã³ã¬ãŒã¿ã®æ¬äœã§return class extends ClassIWasPassed { ... }
ãå®è¡ããããšã«å¶éãããŠããªããããç¹ã«é©åã§ãã奜ããªããšãå®è¡ã§ããŸãã æžç®åããããåããŠããªã³ããããã¯ãã¹ãŠå
¬æ£ãªã²ãŒã ã§ãã çµæãšããŠåŸãããã¿ã€ãã¯ãææ¡ããŠãããã®æšè«ã«ãŒãã§ããŸãæ©èœããå¿
èŠããããŸãã åé¡ã®äŸãšããŠããã®äŸã§äœãèµ·ããã¹ãããæããŠãã ããã
type Constructor<T> = new (...args: any[]) => T
type Greeter = { hello(): string }
function logger<T extends Constructor<Greeter>>(Class: T) {
return class {
hello() {
console.log(new Class().hello()) // Do I get a type error here? After all, the signature of Class is { hello: () => void }
}
};
}
// Or should I get the error here? Foo does not conform to { hello(): string }
<strong i="22">@logger</strong>
class Foo {
hello() { return "foo"; }
}
åé¡ããããªãããŒãã§ãããšããŠåã«æã§æ¯ãããšã¯ã§ããŸããã誰ããå®éã«ãããã©ã®ããã«æ©èœããããææ¡ããå¿ èŠããããŸãã
ãšã©ãŒã§ã¯ãããŸãã-Greeterã«æºæ ããã¯ã©ã¹ãLoggerã«æž¡ããŠããŸãã ãã ããFooã¯ãã³ã¬ãŒã¿ã«ãã£ãŠå®å šã«ç°ãªããã®ã«å€æŽãããGreeterãæ¡åŒµããªããªããŸãã ãããã£ãŠããã¬ãŒãã³ã¬ãŒã¿ãFooãGreeterãšããŠæ±ãããšã¯æå¹ã§ãããFooã¯ãã³ã¬ãŒã¿ã«ãã£ãŠå®å šã«ç°ãªããã®ã«åå²ãåœãŠããããããä»ã®äººã«ã¯ç¡å¹ã§ãã
ãããå®è£ ããã®ã¯æããã«é£ããã§ãããã ãã®ã¹ã¬ããã®å é ã«ãªã¹ããããŠãããããªäžè¬çãªã±ãŒã¹ã§ãã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžãªã©ã®åé¿çããã®ãããªããªãããŒãªãšããžã±ãŒã¹ã®ãã©ãŒã«ããã¯ã§ããå Žåãããã€ãã®åççãªãµãã»ãããå¯èœã§ããïŒ
@arackaf
ãã ããFooã¯ãã³ã¬ãŒã¿ã«ãã£ãŠå®å šã«ç°ãªããã®ã«å€æŽãããŸã
ããããFoo
ãäœã§ãããã«ã€ããŠã®æ£ç¢ºãªå®çŸ©ã¯ãããŸããã ç§ãã¡ã®å
šäœçãªè«ç¹ã¯ã Foo
ã®ã¡ã³ããŒãã¢ã¯ã»ã¹ã§ãããã©ããïŒãããã£ãŠããããªãã¯APIã®äžéšãšããŠæ»ãããšãã§ãããã©ããïŒã§ããããšã«æ³šæããŠãã ããããã³ã¬ãŒã¿ã¯this
ããã¡ã³ããŒã玹ä»ããŸããã Foo
ãšã¯ããã³ã¬ãŒã¿ãè¿ããã®ã«ãã£ãŠå®çŸ©ããããã³ã¬ãŒã¿ãè¿ããã®ã¯ã Foo
ãšã¯äœãã«ãã£ãŠå®çŸ©ãããŸãã ãããã¯äžå¯åã«æ¥åãããŠããŸãã
ãããå®è£ ããã®ã¯éåžžã«é£ãããšç¢ºä¿¡ããŠããŸã
æ©èœãã©ã®ããã«æ©èœãããã«ã€ããŠã®ç¢ºåºããææ¡ãããªãå Žåãå®è£
ã®è€éãã«ã€ããŠè©±ãã®ã¯ãŸã ææå°æ©ã§ãã ç³ãèš³ãããŸããããããã®ãããªäžé£ã®ãã³ã¬ãŒã¿ããã®ãããªã¯ã©ã¹ã«é©çšãããšã this
ã©ããªãããã«ã€ããŠãå
·äœçãªã¡ã«ããºã ãææ¡ããŠããã人ãæ¬åœã«å¿
èŠã§ãã 次ã«ãããŸããŸãªTypeScriptã®æŠå¿µãããŸããŸãªéšåã«ãã©ã°ã€ã³ããŠãäœãæå³ããªããã確èªã§ããŸãã ããããŠåããŠãå®è£
ã®è€éãã«ã€ããŠè°è«ããããšãçã«ããªã£ãŠããŸãã
äžã«è²Œãä»ããçŸåšã®ãã³ã¬ãŒã¿åºåã¯ä»æ§ã«æºæ ããŠããŸãããïŒ ç§ã¯ãããç§ãèŠããã®ããã ãšæããŸããã
ããã ãšããã°ãFooã¯ãããã段éã§ããªãæ£ç¢ºãªæå³ãæã£ãŠããŸãã TSã§ã¯ãæåŸã®ãã³ã¬ãŒã¿ãè¿ããã®ã«åºã¥ããŠthis
ïŒFooã¡ãœããå
ããã³Fooã®ã€ã³ã¹ã¿ã³ã¹ïŒã䜿çšã§ããããã«ãªããšæããŸããTSã§ã¯ããã³ã¬ãŒã¿ã®å Žåãå¿
èŠã«å¿ããŠéäžã§å泚éãè¿œå ããå¿
èŠããããŸããé¢æ°ã¯ååã«åæã§ããŸããã
@arackaf ãéã®ããã¯ãããŸããã ç¹å®ã®äžå€ã³ãŒãã¹ããããã®æçµçãªã¿ã€ãthis
ã®ã¿ã«é¢å¿ããããŸãã ãã³ã¬ãŒã¿é¢æ°f1...fn
ã§è£
食ãããã¯ã©ã¹X
ã®ã¡ã³ããŒã«å¯ŸããŠã this
ã®ã¿ã€ããã©ãããã¹ãããå°ãªããšã倧ãŸãã«èª¬æããå¿
èŠããããŸãã X
ããã³f1...fn
ã®å眲åã®ã ããã»ã¹ã«ã¯ãå¿
èŠãªæ°ã®ã¹ããããå«ããããšãã§ããŸãã ãããŸã§ã®ãšããã誰ããããè¡ã£ãŠããŸããã ç§ã¯äººã
ããã³ã¬ãŒã¿ã®ãªã¿ãŒã³ã¿ã€ããthis
ã®ã¿ã€ããšããŠæ瀺ãããã¹ãã§ããããšãæå³ããŠãããšæšæž¬ããŠããŸããããç§ãç¥ã£ãŠããéãã§ã¯ãç§ã¯å®å
šã«ããŒã¯ããå€ããŠããå¯èœæ§ããããŸãã
ãã©ã³ã¹ãã€ã«ãããåºåã®å€ã«äœãèµ·ãã£ãŠããããã¿ã€ãã«æ©æ¢°çã«åæ ããããšããææ¡ã®å Žåãææ¡ããŠãããã®ã§ã¯ãªããç§ãææ¡ããŠãããã®ã«ãªããŸããã€ãŸãã new Foo().hello()
ã¯åé¡ãããŸãããã this.hello()
ã¯ããã§ã¯ãããŸããã ãã®äŸã®ã©ã®æç¹ã§ããè£
食ããŠããå
ã®ã¯ã©ã¹ã¯hello
ã¡ãœãããååŸããŸããã __decorate([addMethod], Foo)
ïŒæ¬¡ã«Foo
ã«å²ãåœãŠãããïŒã®çµæã®ã¿ãhello
ã¡ãœãããæã¡ãŸãã
ç§ã¯äººã ããã³ã¬ãŒã¿ã®ãªã¿ãŒã³ã¿ã€ããããã®ã¿ã€ããšããŠæ瀺ãããã¹ãã§ããããšãæå³ããŠãããšæšæž¬ããŠããŸãã
ããããã¿ãŸãããã¯ããããã§ãã ãŸãã«ãã®éãã§ãã çµæ¢ç¬Šã ããããã³ã¬ãŒã¿ãè¡ãããšã ããã§ãã è¡ã®æåŸã®ãã³ã¬ãŒã¿ãå®å šã«æ°ããã¯ã©ã¹ãè¿ãå ŽåããããFooã§ãã
èšãæãããšïŒ
<strong i="9">@c</strong>
<strong i="10">@b</strong>
<strong i="11">@a</strong>
class Foo {
}
Fooã¯ãäžçäžã®c
ãèšã£ãŠããããšã§ãã c
ãany
ãè¿ãé¢æ°ã§ããå ŽåãããããŸãããå
ã®Foo
ã«ãã©ãŒã«ããã¯ããã ãã§ããããã ããã¯ãåççã§äžäœäºææ§ã®ããã¢ãããŒãã®ããã§ãã
ãããã c
ãæ°ããã¿ã€ãX
$ãè¿ãå ŽåãFooããããå°éããããšã絶察ã«æåŸ
ããŸãã
ç§ã¯äœãã足ããªãã®ã§ããïŒ
ããã«æ確ã«ããå Žå
class X {
hello() {}
world() {}
}
function c(cl : any) : X { // or should it be typeof X ?????
//...
}
<strong i="25">@c</strong>
<strong i="26">@b</strong>
<strong i="27">@a</strong>
class Foo {
sorry() {}
}
new Foo().hello(); //perfectly valid
new Foo().sorry(); //ERROR
ç§ã¯äœãã足ããªãã®ã§ããïŒ
@arackafã¯ãããã®çŽ æŽãªã¢ãããŒãã«æ¬ ããŠããã®ã¯ããã³ã¬ãŒã¿ãä»»æã®åãèªç±ã«è¿ãããšãã§ãããšããããšã§ããçµæãFoo
ã®åãšäºææ§ããããšããå¶éã¯ãããŸããã
ããªããããã§äœãåºãããšãã§ããäžæ¡çã¯ããã€ããããŸãã this
ã®ã¿ã€ãã«ãã£ãŠæ±ºå®ãããc
ã®çµæãšããŠã this
ãšå
¥åããããšã®åŸªç°æ§ã«ã€ããŠã®ç°è°ãäžæåæ¢ãããšããŸããããã¯ã c
ã®çµæã«ãã£ãŠæ±ºå®ãããŸãã
type Constructor<T> = new (...args: any[]) => T
type Greeter = { hello(): string }
function logger<T extends Constructor<Greeter>>(Class: T) {
return class {
hello() {
console.log(new Class().hello())
}
};
}
<strong i="15">@logger</strong>
class Foo {
foo() { return "bar" }
// Whoops, `this` is `{ hello(): void }`, it has no `foo` method
hello() { return this.foo(); }
}
ãã®å Žåãå®å
šã«ç¡å®³ãªã³ãŒãã«å¯ŸããŠãšã©ãŒãçæãããã this
ããã³ã¬ãŒã¿ã®ãªã¿ãŒã³ã¿ã€ããšå®å
šã«åäžã§ãããšããåœé¡ã調æŽããå¿
èŠããããŸãã
åé¡ãçºçãããã©ããã¯ããããŸããã @logger
ã¯ã foo
ã¡ãœããã䜿çšããã«ããŸã£ããæ°ããhello()
ã¡ãœããã䜿çšããŠããŸã£ããæ°ããã¯ã©ã¹ãè¿ãããšãéžæããŸããã Foo
ã
new Foo().foo()
ãã¯ãæå¹ã§ã¯ãããŸããã ã©ã³ã¿ã€ã ãšã©ãŒãçºçããŸãã ã³ã³ãã€ã«æã®ãšã©ãŒãçºçããã¯ãã ãšèšã£ãŠããã ãã§ãã
ãšã¯ãããããããã¹ãŠãéçã«åæããã®ãé£ããããå Žåã¯ãè¿ããããã®ãæ£ç¢ºã«ç€ºãããã«ãæ瀺çãªå泚éãlogger
ã«è¿œå ããããã«åŒ·å¶ããããšã¯å®å
šã«åççã§ãã ãããŠããã®ãããªåã®æ³šéãååšããªãå Žåã¯ã Foo
ãè¿ããããšä»®å®ããããšã«æ»ããŸãã ããã«ãããäžäœäºææ§ãç¶æãããŸãã
@arackafå
¥åãå®è¡æã®è©äŸ¡ã«é¢ããŠã¯ãã³ãŒãã«åé¡ã¯ãããŸããã new Foo().hello()
ãåŒã³åºãããšãã§ããŸããããã«ãããè£
食ãããã¯ã©ã¹ã®hello
ãå
éšçã«åŒã³åºãããè£
食ãããã¯ã©ã¹ã®bar
ãåŒã³åºãããŸãã å
ã®ã¯ã©ã¹å
ã§bar
ãåŒã³åºãããšã¯ãšã©ãŒã§ã¯ãããŸããã
éã³å Žã§ãã®å®å šãªäŸãå®è¡ããããšã«ãããèªåã§è©ŠããŠã¿ãããšãã§ããŸãã
// Code from previous snippet...
const LoggerFoo = logger(Foo)
new LoggerFoo().hello()
確ãã«-ããããåŒã³åºãã®ã¯ãšã©ãŒã ãšèšã£ã
new Foo().foo()
å ¥åãå®è¡æã®è©äŸ¡ã«é¢ããŠã¯ãã³ãŒãã«åé¡ã¯ãããŸããã new FooïŒïŒãhelloïŒïŒãåŒã³åºãããšãã§ããŸããããã«ãããè£ é£Ÿãããã¯ã©ã¹ã®helloãå éšçã«åŒã³åºãããè£ é£Ÿãããã¯ã©ã¹ã®ããŒãåŒã³åºãããŸãã
ããããèšãã®ã¯ééãã§ã
let s : string = new Foo().hello();
Fooã®helloã¡ãœããã¯ãLoggerãè¿ãã¯ã©ã¹ããšã«ãvoidãè¿ãããã«ãªããŸããã
ãã¡ããã§ããã
new Foo().foo()
ãåŒã³åºãã®ã¯ãšã©ãŒã ãšèšããŸãã
@arackafããããããã¯åé¡ã§ã¯ãããŸããã new Foo().foo()
ãåŒã³åºããªãã£ãã this.foo()
ãåŒã³åºãããšãããå®è¡æã«ã³ãŒããæ£åžžã«æ©èœããŠããŠããåãšã©ãŒãçºçããŸããã
ãããã
let s : string = new Foo().hello()
ãšèšãã®ã¯ééãã§ãã
ç¹°ãè¿ããŸãããããã¯é¢ä¿ãããŸããã Foo.prototype.hello
() => string
ã«ããå¿
èŠããããšèšã£ãŠããã®ã§ã¯ãããŸããïŒ () => void
ã«ããå¿
èŠãããããšã«åæããŸãïŒã 移æ€ããã®ãç¡æå³ãªã¿ã€ããå€ç§çã«ç§»æ€ããã®ã§ãæå¹ãªåŒã³åºãthis.bar()
ããšã©ãŒã«ãªãããšã«ã€ããŠäžå¹³ãèšã£ãŠããŸãã
ããã«ã¯2ã€ã®FooããããŸãã ããªããèšãæ
class Foo {
}
Fooã¯ãã¯ã©ã¹å ã®äžå€ã®ãã€ã³ãã£ã³ã°ã§ãããã¯ã©ã¹å€ã®å¯å€ã®ãã€ã³ãã£ã³ã°ã§ãã ãããã£ãŠãããã¯jsbinã§ç¢ºèªã§ããããã«å®å šã«æ©èœããŸã
class Foo {
static sMethod(){
alert('works');
}
hello(){
Foo.sMethod();
}
}
let F = Foo;
Foo = null;
new F().hello();
äžèšã®äŸã§ãåæ§ã®ããšãè¡ãããŸãã å€éšãã€ã³ãã£ã³ã°ãå€æŽãããåã«ãå ã®ã¯ã©ã¹ãžã®åç §ããã£ããã£ããŸãã äœãé転ããŠããã®ããŸã ããããŸããã
this.foo();
ã¯å®å
šã«æå¹ã§ãããåãšã©ãŒã¯äºæ³ãããŸããïŒåç
§ãå¿
èŠãªå Žåã§ããTSã®æ
åœè
ãéé£ããããšã¯ãããŸãããããã远跡ããã®ã¯é£ãããšç¢ºä¿¡ããŠããããã§ãïŒã
this.foo();
ã¯å®å šã«æå¹ã§ãããã¿ã€ããšã©ãŒã¯çºçããªããšæããŸã
è¯ãã®ã§ãåæããŸãããããã¯ã this
ããã³ã¬ãŒã¿ãè¿ããã®ã®ã€ã³ã¹ã¿ã³ã¹ã¿ã€ãã§ãããšããææ¡ã修食ãŸãã¯åŽäžããå¿
èŠãããããšãæå³ããŸãã ã¿ã€ããšã©ãŒã§ã¯ãªããšæãå Žåãç§ã®äŸã§ã¯{ hello(): void }
this
ã䜿çšããå¿
èŠããããŸããïŒ
this
ã¯ãã€ã³ã¹ã¿ã³ã¹åããããã®ã«ãã£ãŠç°ãªããŸãã
<strong i="7">@c</strong>
class Foo{
}
new Foo(). // <---- this is based on whatever c returned
function c(Cl){
new Cl(). // <----- this is an object whose prototype is the original Foo's prototype
// but for TS's purpose, for type errors, it'd depend on how Cl is typed
}
å ·äœçãªäŸãäžã€æããŠããã ããŸãããã ããããã°ãç§ã¯ç©äºãã¯ããã«ç解ãããããªããŸãã 次ã®ã¹ããããïŒ
type Constructor<T> = new (...args: any[]) => T
type Greeter = { hello(): string }
function logger<T extends Constructor<Greeter>>(Class: T) {
return class {
hello() {
console.log(new Class().hello())
}
};
}
<strong i="6">@logger</strong>
class Foo {
foo() { return "bar" }
hello() { return this.foo(); } /// <------
}
this
ã®çš®é¡ã¯äœã§ããïŒ { hello(): void }
ã®å Žåã foo
ã¯{ hello(): void }
ã®ã¡ã³ããŒã§ã¯ãªããããã¿ã€ããšã©ãŒãçºçããŸãã { hello(): void }
ã§ãªãå Žåã this
ã¯åã«ãã³ã¬ãŒã¿ã®æ»ãåã®ã€ã³ã¹ã¿ã³ã¹åã§ã¯ãªãããã this
ã®åã«å°éããããã«äœ¿çšããŠãã代æ¿ããžãã¯ã説æããå¿
èŠããããŸãã
ç·šéïŒ Foo
ã«ãã³ã¬ãŒã¿ãè¿œå ããã®ãå¿ããŸããã ä¿®çæžã¿ã
ç¢å°ãããthis
ã¯ããã¡ããå
ã®Foo
ã®ã€ã³ã¹ã¿ã³ã¹ã§ãã ã¿ã€ããšã©ãŒã¯ãããŸããã
ãã-ç§ã¯ä»ããªãã®äž»åŒµãç解ããŠããŸãã ããããç§ã¯ãŸã åé¡ãã©ãã«ããã®ãããããŸããã this.foo()
å
ã®Fooå
ã¯ãåãšã©ãŒã§ã¯ãããŸãããããã¯ã以åã¯èå¥åFoo
ã«ãã€ã³ããããŠããïŒçŸåšã¯å°éäžèœãªïŒã¯ã©ã¹ã«æå¹ã§ãã
ããã¯ç¹ç°ã§æ¥œããéåŠã§ãããTSãå€åããã¯ã©ã¹ãã³ã¬ãŒã¿ãåŠçã§ããªãçç±ãããããŸããã
@arackafããªãã¯è³ªåã«çããŠããŸããã å
·äœçã«ã¯ã this
ã®ã¿ã€ãã¯äœã§ããïŒ ã this
ã¯Fooã§ãããFooã¯this
ã§ãããšç¡éã«åŸªç°çã«çããããšã¯ã§ããŸããã this
ã«ã¯ã©ã®ãããªã¡ã³ããŒãããŸããïŒ hello(): void
以å€ã®ã¡ã³ããŒãããå Žåããããã決å®ããããã«ã©ã®ããžãã¯ã䜿çšãããŠããŸããïŒ
ãå
ã®Fooå
ã®this.foo()
ã¯ã¿ã€ããšã©ãŒã§ã¯ãããŸããããšèšãå Žåã§ãã次ã®è³ªåã«çããå¿
èŠããããŸããã¿ã€ããšã©ãŒã§ã¯ãªããããªthis
ã®æ§é ã¿ã€ãã¯äœã§ããã this.foo()
å®è¡ããŸããïŒ
ãŸããå
ã®ã¯ã©ã¹ã¯ãå°éäžèœãã§ã¯ãããŸããã ãã®ã³ãŒãã¹ããããã§å®çŸ©ããããã¹ãŠã®é¢æ°ã¯ãå®è¡æã«ã¢ã¯ãã£ãã«å®è¡ããããã¹ãŠåé¡ãªãæ©èœããŸãã ç§ãæäŸããéã³å Žã®ãªã³ã¯ãå®è¡ããã³ã³ãœãŒã«ãèŠãŠãã ããã ãã³ã¬ãŒã¿ã¯ã hello
ã¡ãœãããè£
食ãããã¯ã©ã¹ã®hello
ã¡ãœããã«å§ä»»ããæ°ããã¯ã©ã¹ãè¿ããŸãã次ã«ãè£
食ãããã¯ã©ã¹ã®foo
ã¡ãœããã«å§ä»»ããŸãã
ããã¯ç¹ç°ã§æ¥œããéåŠã§ãããTSãå€åããã¯ã©ã¹ãã³ã¬ãŒã¿ãåŠçã§ããªãçç±ãããããŸããã
åã·ã¹ãã ã«ã¯ãããªãã¢ãã¯ãããŸããã ãŠãŒã¹ã±ãŒã¹ããããããããããTSC-1234ã®ãããããã£åãããã¯ã§ããŸããããšããã¿ã€ãã®ãšã©ãŒã¯çºçããŸããã æ©èœãåå ã§å®å šã«æ£åžžãªã³ãŒããé©ãã¹ãæ¹æ³ã§å£ããŠããå Žåã¯ããã®æ©èœãåèããå¿ èŠããããŸãã
ãŠãŒã¹ã±ãŒã¹ããããããããããTSC-1234ã®ãããããã£åãããã¯ã§ããŸããããšããã¿ã€ãã®ãšã©ãŒã¯çºçããŸããã
ããã¯ããã³ã¬ãŒã¿ã«ãã£ãŠã¯ã©ã¹å®çŸ©ã«è¿œå ãããã¡ãœããã䜿çšããããšãããšãã«åŸããããã®ãšãŸã£ããåãã§ãã çŸåšãã¯ã©ã¹ã«å®çŸ©ãè¿œå ããããã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžã any
ãšããŠã®ãã£ã¹ããªã©ã䜿çšããŠããã®åé¡ãåé¿ããå¿
èŠããããŸãã
this
ãšã¯äœããã©ãã«ãããã«ã€ããŠã®ãã¹ãŠã®è³ªåã«çããŸããã
åé¡ã®åçŽãªäºå®ã¯ã this
ã®æå³ãããªããã©ãã«ãããã«åºã¥ããŠå€ãããšããããšã§ãã
type Constructor<T> = new (...args: any[]) => T
type Greeter = { hello(): string }
function logger<T extends Constructor<Greeter>>(Class: T) {
return class {
hello() {
console.log(new Class().hello())
}
};
}
class Foo {
foo() { return "bar" }
hello() { return this.foo(); } /// <------
}
const LoggableFoo = logger(Foo)
new LoggableFoo().hello() // Logs "bar"
new Class()
ãšèšããš-ã¯ã©ã¹ã¯å
ã®FooãæããŠãããTypeScriptã®èŠ³ç¹ããã¯ã hello(): string
ã«ã¢ã¯ã»ã¹ã§ããŸããããã¯ãã¯ã©ã¹ãå
¥åããããã®ã§ããããã§ãïŒGreeterãæ¡åŒµããŸãïŒã å®è¡æã«ãå
ã®Fooã®ã€ã³ã¹ã¿ã³ã¹ãã€ã³ã¹ã¿ã³ã¹åããŸãã
new LoggableFoo().hello()
ã¯ãGreeterãä»ããŠå
¥åããããä»ã®æ¹æ³ã§ã¯å°éã§ããªãã¡ãœãããåŒã³åºãvoidã¡ãœãããããŸããŸåŒã³åºããŸãã
ããªãããã£ããªã
<strong i="21">@logger</strong>
class Foo {
foo() { return "bar" }
hello() { return this.foo(); }
}
ããã§ãFooã¯helloïŒïŒã®ã¿ãæã€ã¯ã©ã¹ã«ãªããŸããvoidããã³new FooïŒïŒãfooïŒïŒã¯Typeãšã©ãŒã«ãªãã¯ãã§ãã
ãŸãã hello() { return this.foo(); }
ã¯TypeErrorã§ã¯ãããŸãã-ãªããããªãã®ã§ããããïŒ ãã®ã¯ã©ã¹å®çŸ©ã«å°éã§ããªããªã£ããããšãã£ãŠãã©ãããããããã®ã¡ãœãããç¡å¹ã«ãªãããã§ã¯ãããŸããã
TypeScriptããããã®ãšããžã±ãŒã¹ã®ãããããå®ç§ã«ããããšã¯æåŸ
ããŠããŸããã ãã€ãã®ããã«ããã¡ãã¡ã«å泚éãè¿œå ããªããã°ãªããªãããšã¯ããªãç解ã§ããã§ãããã ãããããããã®äŸã®ããããã @logger
ãFoo
ã®ãã€ã³ãå
ãæ ¹æ¬çã«å€æŽã§ããªãçç±ã瀺ããŠããŸããã
logger
ãæ°ããã¯ã©ã¹ãè¿ãé¢æ°ã§ããå ŽåããããFooãçŸåšåç
§ããŠãããã®ã§ãã
ç§ã¯ãããäœã§ãããããããŠã©ãã§ãããã«ã€ããŠã®ãã¹ãŠã®è³ªåã«çããŸããã
åé¡ã®åçŽãªäºå®ã¯ãthis
ã®æå³ãããªããã©ãã«ãããã«åºã¥ããŠå€ãããšããããšã§ãã
ããã¯æ¬åœã«ã€ã©ã€ã©ããŸãã ããã§ããããããã¯å€ãããŸããããã¯Foo
ã§ããããã¯éçãã€ã³ãã£ã³ã°ãªã©ã§ãããªã©ãªã©ãå眲åãšã¯äœã§ããïŒ this
ã«ã¯ã©ã®ãããªã¡ã³ããŒãããŸããïŒ ããªãã¯å€ªéœã®äžã§ãã¹ãŠã«ã€ããŠè©±ããŠããã®ã§ãããç§ãããªãããå¿
èŠãšããŠããã®ã¯ã this
ãhello
ã®äžã«ãããã®ã®åçŽãªå眲åã ãã§ãã
new LoggableFoo().hello()
ã¯ãGreeterãä»ããŠå ¥åããããä»ã®æ¹æ³ã§ã¯å°éã§ããªãã¡ãœãããåŒã³åºãvoidã¡ãœãããããŸããŸåŒã³åºããŸãã
ããã¯å°éäžèœãšåãã§ã¯ãããŸããã å°éå¯èœãªãã¹ãŠã®ã¡ãœããã¯ãå°éå¯èœãªãã¹ãå²ãåŒããšãå°éäžå¯èœãã«ãªããŸãã
è¡ã£ãå ŽåïŒ
ããããããã¯æåéãç§ãããããšã§ãã ããã¯ãŸãã«ç§ã®ã³ãŒãã¹ããããã§ãããå床貌ãä»ããŠãåã«äœæããäŸã®èª¬æãä»ããŠããŸãã ã¯ã¬ã€ãžãŒãªãã«ãæçšããŠããªãããšã確èªããããã«ãå·®åãã§ãã«ãŒãå®è¡ããŸãããå¯äžã®éãã¯ãåé€ããã³ã¡ã³ãã§ãã
ãŸãã
hello() { return this.foo(); }
ã¯TypeErrorã§ã¯ãããŸãã-ãªããããªãã®ã§ããããïŒ
ããªãïŒãããŠããã«ããä»ã®äººãã¡ïŒã¯this
ã®ã¿ã€ãããã³ã¬ãŒã¿ã®ã€ã³ã¹ã¿ã³ã¹åããããªã¿ãŒã³ã¿ã€ããã€ãŸã{ hello(): void }
ã«ãããããã§ãïŒ foo
ã¡ã³ããŒãããªãããšã«æ³šæããŠãã ããïŒã Foo
this
ããã³ã¬ãŒã¿ã®ãªã¿ãŒã³ã¿ã€ããšããŠè¡šç€ºã§ããããã«ããå Žåã hello
this
ã®ã¿ã€ãã¯{ hello(): void }
ã«ãªããŸãã { hello(): void }
ã®å Žåãã¿ã€ããšã©ãŒãçºçããŸãã ã¿ã€ããšã©ãŒãçºçããå Žåãã³ãŒããæ£åžžã«å®è¡ããããããæ²ããã§ãã
ã¿ã€ããšã©ãŒã§ã¯ãªããšèšãå Žåã¯ããã³ã¬ãŒã¿ã®ãªã¿ãŒã³ã¿ã€ããä»ããŠthis
ã®ã¿ã€ããæäŸããããã®ç¬èªã®ã¹ããŒã ãæŸæ£ããŠããŸãã this
ã®ã¿ã€ãã¯ããã³ã¬ãŒã¿ãäœãè¿ããã«é¢ä¿ãªãã { hello(): string; bar(): string }
ã«ãªããŸãã ãã®åé¡ãåé¿ããthis
ã®ã¿ã€ããçæããããã®ä»£æ¿ã¹ããŒã ããããããããŸãããããããäœã§ããããæå®ããå¿
èŠããããŸãã
ãã³ã¬ãŒã¿ã®å®è¡åŸã Foo
ããæåã«å®çŸ©ããããã®ãšã¯ãŸã£ããå¥ã®äœããåç
§ã§ããããšãç解ããŠããªãããã§ãã
function a(C){
return class {
x(){}
y(){}
z(){}
}
}
<strong i="7">@a</strong>
class Foo {
a(){
this.b(); //valid
}
b() {
this.c(); //also valid
}
c(){
return 0;
}
}
let f = new Foo();
f.x(); //valid
f.y(); //also valid
f.z(); //still valid
this
ã¯ãïŒãã³ã¬ãŒã¿ã®å®è¡åŸïŒæçµçã«Foo
ããäœæãããã€ã³ã¹ã¿ã³ã¹ã®å Žåãšã¯ç°ãªããäžèšã®Fooã®å
éšã§äœãéãããšã«æ°ä»ããšæããŸããïŒ
äœãèšãã°ããã®ãããããããŸããã ããããã³ã¬ãŒã¿ã®ä»çµã¿ã§ãã ç§ã®å¯äžã®è°è«ã¯ãTypeScriptã¯èµ·ãã£ãŠããããšã«ãã£ãšå³å¯ã«äžèŽããã¹ãã ãšããããšã§ãã
å¥ã®èšãæ¹ãããã°ãïŒå ã®ïŒFooå ã®åã¢ãããŒã·ã§ã³ã¯ããã³ã¬ãŒã¿ãå®è¡ãããåŸã®Fooãçæãããã®ãšã¯ç°ãªããŸãã
å¥ã®èšèªããé¡æšãããšãè£
食ãããFoo
å
ã§ã¯ãããã¯CïŒå¿ååãšåçã®ãã®ãåç
§ããŸããããã¯å®å
šã«å®éã®åã§ããããã以å€ã®å Žåã¯æå¹ã§ãããçŽæ¥åç
§ããããšã¯ã§ããŸããã äžèšã®ãšã©ãŒãšéãšã©ãŒãååŸããã®ã¯å¥åŠã«èŠããŸãããç¹°ãè¿ãã«ãªããŸãããããããŸãã«ãã®ä»çµã¿ã§ãã ãã³ã¬ãŒã¿ã¯ããã®ãããªå¥åŠãªããšãè¡ãããã®éæ¹ããªãåãç§ãã¡ã«äžããŠãããŸãã
ãããäžèšã®Fooã®å éšã§äœãéãããšã«æ°ä»ãããšæããŸãããããã¯ãFooãæçµçã«ïŒãã³ã¬ãŒã¿ãå®è¡ãããåŸïŒäœã§ãããããåŸã§äœæãããå Žåãšã¯ç°ãªããŸããïŒ
ãããã200件åã«ææ¡ããŠãããã®ãšãŸã£ããåããªã®ã§ããã®äžã«å¥åŠãªç¹ã¯ãããŸããã åã®è°è«ã®ãããããèªãã ããšãããããŸããïŒ
ããªããæçš¿ããã¹ããããã¯ãŸã£ããè°è«ã®äœå°ããããŸããã ç§ãå察ããŠãã人ã ããããŠããªãããžã£ã³ãããŠå©ããæ±ãã人ã ã¯ãããã«æ¬¡ã®ãã®ãæãã§ããŸããïŒ
function a(C){
return class {
x(){}
y(){}
z(){}
}
}
<strong i="10">@a</strong>
class Foo {
a(){
this.b(); //valid
}
b() {
this.c(); //also valid
}
c(){
return 0;
}
d(){
// HERE: All of these are also expected to be valid
this.x();
this.y();
this.z();
}
}
let f = new Foo();
f.x(); //valid
f.y(); //also valid
f.z(); //still valid
ç§ã¯ããããã£ãããšè¡ãããšãå¯èœã§ããããšã«åæããããã®ãããªææ¡ãã©ã®ããã«æ©èœããããå¿
æ»ã«ç解ããããšããŠããŸããã ç§ã®æåã®åªåã«ãããããããç§ã¯this
ãæã€ãšäºæ³ãããã¡ã³ããŒã®å
æ¬çãªãªã¹ãããŸãã¯ãã®ãããªãªã¹ããææ¡ã®äžã§ã©ã®ããã«æ§ç¯ãããããæœåºããããšã¯ã§ããŸããã
å¥ã®èšãæ¹ãããã°ãïŒå ã®ïŒFooå ã®åã¢ãããŒã·ã§ã³ã¯ããã³ã¬ãŒã¿ãå®è¡ãããåŸã®Fooãçæãããã®ãšã¯ç°ãªããŸãã
ããã§ããªãããªãã¯ç§ãšè°è«ããããŠããã®ã§ããïŒ ãã¿ã€ããšã©ãŒã§ããæ°ããFooïŒïŒãfooã¯ãã°ã§ãããç°¡åã«ä¿®æ£ã§ããããšã«åæããŸããthis.fooãè¿ãããšã«åæããŸãããã¿ã€ããšã©ãŒã§ããããšããã°ã§ããã åæ§ã«ãããªãã®äŸã§ã¯ãã¿ã€ããšã©ãŒã§ããnew Foo().x()
ã¯ãã°ã§ãããã¿ã€ããšã©ãŒã§ããthis.x()
ã¯ãã°ã§ã¯ãªãããšã«åæããŸãã
ãã®ããŒãžã®äžéšã«ããã¹ããããã«2ã€ã®ã³ã¡ã³ããããããšãããããŸããïŒ
return this.foo; // Property 'foo' does not exist on type 'Foo'
^ããã¯ç§ãåé¡ã ãšæããã®ã§ãã ãã³ã¬ãŒã¿ã®ãªã¿ãŒã³ã¿ã€ãã¯this
ã«è¡šç€ºãããã¹ãã§ã¯ãªãã new Foo()
ã«ã®ã¿è¡šç€ºãããããšã«åæãããããã®å Žåãã©ã¡ããäœãè°è«ããŠããŸããã ãŸãã¯ãåæããããã®æ©èœãå¿
èŠã§ãããã®å Žåãåã®ã³ã¡ã³ãã®ã¹ããããã¯é¢ä¿ãããŸããã
ç§ã¯ã€ãã«ããªãã®äž»åŒµãç解ããŸããã ãããGreeterã³ãŒãããååŸããã®ã¯éåžžã«å°é£ã§ããããçŸåšè¿œè·¡äžã§ãã èŸæ±åŒ·ãããããšãããããŸãã
å¯äžã®è³¢æãªè§£æ±ºçã¯ãFooïŒFooã®å
éšïŒãå
ã®Fooã®åå
±çšäœïŒderpãã€ãŸã亀差ãæå³ããïŒãããã³æåŸã®ãã³ã¬ãŒã¿ãè¿ããã®ããµããŒãããããšã ãšæããŸãã Greeterã®ãããªã¯ã¬ã€ãžãŒãªäŸã§ã¯ãå
ã®Foo
ããµããŒãããå¿
èŠããããŸãããŸãããã³ã¬ãŒã¿ã䜿çšããããšã®å
šäœçãªãã€ã³ãã§ãããããæåŸã®ãã³ã¬ãŒã¿ãè¿ããã®ã¯ãã¹ãŠãµããŒãããå¿
èŠããããŸãïŒäžèšã®å€ãã®ã³ã¡ã³ãã«ããïŒã
ããã§ãããç§ã®ææ°ã®äŸããã Foo
xãyãzãaãbãcã®å
éšã¯ãã¹ãŠæ©èœããŸãã a
ã®ããŒãžã§ã³ã2ã€ããå Žåã¯ãäž¡æ¹ããµããŒãããŸãã
@arackaf npãããªãã®å¿èã«ãæè¬ããŸãã ç§ã®äŸã¯ããããã©ã®ããã«å£ããŠãããã瀺ãããã«éã³å Žã§èª¿çã§ãããã®ãæçš¿ããŠããã ããªã®ã§ãæãæ確ã§ã¯ãããŸããã§ããã äœç³»çã«èããã®ã¯é£ããã§ãã
å¯äžã®è³¢æãªè§£æ±ºçã¯ãFooïŒFooã®å éšïŒãå ã®Fooã®åå ±çšäœãããã³æåŸã®ãã³ã¬ãŒã¿ãè¿ããã®ããµããŒãããããšã ãšæããŸãã
çŽ æŽãããã§ããããã§ç§ãã¡ã¯ä»ããã®è©³çŽ°ã«åãæãã£ãŠããŸãã ãããééã£ãŠããå Žåã¯èšæ£ããŠãã ããããã ããããŠããªã³ããšèšãå Žåã¯ãäž¡æ¹ã®ã¿ã€ãã¡ã³ããŒãå«ãŸããŠããå¿
èŠããããŸããã€ãŸãã A & B
ã§ããå¿
èŠããããŸãã ãããã£ãŠã this
ãtypeof(new OriginalClass()) & typeof(new (decorators(OriginalClass)))
ã«ããŸããããã§ã decorators
ã¯ããã¹ãŠã®ãã³ã¬ãŒã¿ã®åæåã¢ãããŒã·ã§ã³ã§ãã å¹³æãªè±èªã§ã¯ã this
ãããã¹ãŠã®ãã³ã¬ãŒã¿ãééãããå
ã®ã¯ã©ã¹ãã®ã€ã³ã¹ã¿ã³ã¹åãããã¿ã€ããšãå
ã®ã¯ã©ã¹ãã®ã€ã³ã¹ã¿ã³ã¹åãããã¿ã€ãã®å
±ééšåã«ããŸãã
ããã«ã¯2ã€ã®åé¡ããããŸãã 1ã€ã¯ãç§ã®äŸã®ããã«ãååšããªãã¡ã³ããŒã«ã¢ã¯ã»ã¹ã§ããããã«ããããšã§ãã ãã³ã¬ãŒã¿ã«å€æ°ã®ã¡ã³ããŒãè¿œå ããããšãã§ããŸãããã¯ã©ã¹ã§this.newMethod()
ã䜿çšããŠãããã«ã¢ã¯ã»ã¹ããããšãããšãå®è¡æã«åãåºãããŸãã newMethod
ã¯ããã³ã¬ãŒã¿é¢æ°ããè¿ãããã¯ã©ã¹ã«ã®ã¿è¿œå ãããå
ã®ã¯ã©ã¹ã®ã¡ã³ããŒã¯ããã«ã¢ã¯ã»ã¹ã§ããŸããïŒç¹ã«return class extends OriginalClass { newMethod() { } }
ãã¿ãŒã³ã䜿çšããªãéãïŒã
ãã1ã€ã®åé¡ã¯ããå
ã®ã¯ã©ã¹ããæ確ã«å®çŸ©ãããæŠå¿µã§ã¯ãªãããšã§ãã this
ããè£
食ãããã¡ã³ããŒã«ã¢ã¯ã»ã¹ã§ããå Žåã¯ãããããreturnã¹ããŒãã¡ã³ãã®äžéšãšããŠäœ¿çšããããšãã§ããããããå
ã®ã¯ã©ã¹ãã®ãããªãã¯APIã®äžéšã§ããå¯èœæ§ããããŸãã ç§ã¯ããã§ã¡ãã£ãšæãæ¯ã£ãŠããŠãå
·äœçãªäŸãèããã«ã¯å°ãçãå°œããããŠããŸãããããã«ã€ããŠããèããã°ãç¡æå³ãªäŸãæãã€ãããšãã§ãããšæããŸãã ãã¶ãã this
ããã¢ã¯ã»ã¹ãããã®ãè¿ããªãã¡ã³ããŒããŸãã¯å°ãªããšãthis.something()
ãè¿ããçµæãšããŠæ»ãã¿ã€ããæšæž¬ãããªãã¡ã³ããŒãåé¢ããæ¹æ³ãèŠã€ããããšã§ããããåé¿ã§ããŸãã
@masaeeduãããç§ã¯ããªãã®è¿äºã®åã«åéå/亀差ç¹ã«ã€ããŠèªåèªèº«ãèšæ£ããŸããã TSãåããŠäœ¿çšãã人ã«ãšã£ãŠã¯çŽæã«åããŸãã
æ®ãã®éšåãç解ããŸããã æ£çŽãªãšããããã³ã¬ãŒã¿ã¯éåžžãå®å šã«ç°ãªãã¿ã€ããè¿ãããšã¯ãããŸãããéåžžãæž¡ãããã¿ã€ããæ¡åŒµããã ããªã®ã§ã亀差ç¹ã¯ã»ãšãã©ã®å Žåå®å šã«ãæ©èœãããŸãã
ããªãã話ããŠããã©ã³ã¿ã€ã ãšã©ãŒã¯ãŸãã§ãããæå³çã«æªãéçºæ±ºå®ã®çµæã ãšæããŸãã ãããæ¬åœã«æ°ã«ããå¿ èŠããããã©ããã¯ããããŸãããããããæ¬åœã«åé¡ã§ããå Žåã¯ãæåŸã«è¿ããããã³ã¬ãŒã¿ã䜿çšããã ãã§ããŸãšããª2äœã«ãªããšæããŸãïŒã€ãŸããã¯ã©ã¹ã¯TypeErrorã次ã®ããã«èŠãããšãã§ããŸãïŒããèªäœãå®çŸ©ããæ¹æ³ã䜿çšããããšããŠããŸã-çæ³çã§ã¯ãããŸãããããã³ã¬ãŒã¿ã®åäœã«æ¯æã䟡å€ã®ããäŸ¡æ Œã§ãïŒã
ããããå®éã«ã¯ããã³ã¬ãŒã¿ãæ£ããæ©èœããããšãç ç²ã«ããŠãããªããèããŠããã©ã³ã¿ã€ã ãšã©ãŒãé²ã䟡å€ã¯ãªããšæããŸãã ããã«ãäžæ³šæãŸãã¯ã°ãããŠããå ŽåãTSã§ã©ã³ã¿ã€ã ãšã©ãŒãçæããã®ã¯éåžžã«ç°¡åã§ãã
interface C { a(); }
class C {
foo() {
this.a(); //<--- boom
}
}
let c = new C();
c.foo();
ããªãã®2çªç®ã®ç°è°ã«ã€ããŠ
returnã¹ããŒãã¡ã³ãã®äžéšãšããŠäœ¿çšããããšãã§ããããããå ã®ã¯ã©ã¹ãã®ãããªãã¯APIã®äžéšã§ããå¯èœæ§ããããŸãã
æãå ¥ããŸãããåé¡ã¯ãããŸããã ãã³ã¬ãŒã¿ãä»ããŠã¯ã©ã¹ã«è¿œå ããããã®ã¯ãã¹ãŠã絶察ã«äžçŽåžæ°ã«ãªãããã§ãã æœåšçãªåé¡ãäœã§ãããèå³ããããŸãã
ãã1ã€ã®è¯ããªãã·ã§ã³ã¯ããããéšåçã«ã®ã¿å®è£ ããããšã ãšæããŸãã
çŸåšãã¯ã©ã¹ã¯å®çŸ©ããããšããã«åžžã«åæå®ãããŠããŸãã ãããã£ãŠãFooå ã§ã¯ãããã¯ãã³ã¬ãŒã¿ã«é¢ä¿ãªããfooãå®çŸ©ãããŠããæ¹æ³ã«åºã¥ããŠããŸãã ãã³ã¬ãŒã¿ã®ãŠãŒã¹ã±ãŒã¹ã®ããã€ãã®æçšãªãµãã»ããïŒã€ãŸããæãäžè¬çãªãã®ïŒã«ã€ããŠããããããã ãæ¡åŒµããããšã¯ãéåžžã«å€§ããªæ¹åã«ãªãã§ãããã
ãã³ã¬ãŒã¿ãå
ã®ã¯ã©ã¹ãæ¡åŒµãããã®ãè¿ãå Žåã«ã®ã¿ãã¯ã©ã¹ã®æ¡åŒµãïŒã¯ã©ã¹å
ã®this
ã®èŠ³ç¹ããïŒèš±å¯ãããšã©ããªããŸããïŒ
function d(Class) {
return class extends Class {
blah() { }
};
}
<strong i="9">@d</strong>
class Foo {
a() { }
b() { }
c() {
this.blah(); // <---- valid
}
}
ãããæ£ããæ©èœããããã³ã¬ãŒã¿ã«ãã£ãŠè¿œå ãããäœãšãäœã§ãäžæµã®ãµããŒããæäŸããŸãã ãŸãããŸã£ããæ°ããã¯ã©ã¹ïŒGreeterãªã©ïŒãè¿ããªã©ã®ã¯ã¬ã€ãžãŒãªããšãè¡ããŠãŒã¹ã±ãŒã¹ã§ã¯ãçŸåšã®åäœãç¶è¡ãããã³ã¬ãŒã¿ãå®è¡ããŠããããšãç¡èŠããŸãã
ãšããã§ãããªããäœãéžãã ãã«é¢ä¿ãªããç§ã¯ãããã©ã®ããã«æ³šéããŸããïŒ ããã«çŸåšæ³šéãä»ããããšã¯ã§ããŸããïŒ ç§ã¯è©Šãã
function d<T>(Class: new() => T): T & { new (): { blah(): void } } {
return class extends Class {
blah() { }
};
}
ãã®ããŒãã®å€ãã®ããªãšãŒã·ã§ã³ãšåæ§ã«ãTypeScriptã«ã¯ããããããŸããã§ãã:)
@arackafãã³ã¬ãŒã¿ã¯åãªãé¢æ°ã§ãã äžè¬çãªã±ãŒã¹ã§ã¯ãã©ããã®.d.ts
ãã¡ã€ã«ããååŸããã©ã®ããã«å®è£
ãããŠãããããããŸããã å®è£
ããŸã£ããæ°ããã¯ã©ã¹ãè¿ãã®ããå
ã®ã¯ã©ã¹ã®ãããã¿ã€ãã®ã¡ã³ããŒãè¿œå /æžç®/眮æããŠè¿ãã®ããå
ã®ã¯ã©ã¹ãæ¡åŒµããã®ãã¯ããããŸããã 䜿çšã§ããã®ã¯ãé¢æ°ã®æ§é äœãªã¿ãŒã³ã¿ã€ãã ãã§ãã
ãã³ã¬ãŒã¿ãã¯ã©ã¹ã®ç¶æ¿ã«äœããã®åœ¢ã§çµã³ä»ãããå Žåã¯ãæåã«JSã®å¥ã®èšèªæŠå¿µãææ¡ããå¿
èŠããããŸãã ä»æ¥ã®ãã³ã¬ãŒã¿ã®åäœã¯ãäžè¬çãªã±ãŒã¹ã§this
ãå€æŽããããšãæ£åœåãããã®ã§ã¯ãããŸããã äŸãšããŠãç§ã¯å人çã«åžžã«ç¶æ¿ãããæ§æã奜ã¿ãåžžã«æ¬¡ã®ããšãè¡ããŸãã
function logger<T extends Constructor<Greeter>>(Class: T) {
return class {
readonly _impl;
constructor() {
this._impl = new Class()
}
// Use _impl ...
};
}
ããã¯ã¯ã¬ã€ãžãŒãªåŠè¡å®éšã§ã¯ãªããããã¯ã¹ã€ã³ãè¡ãããã®æšæºçãªã¢ãããŒãã§ãããç§ãããªãã«äžããäŸãšã¯ç°ãªããŸãã å®éã return class extends Class
以å€ã®ã»ãšãã©ãã¹ãŠã¯ãç§ãããªãã«äžããäŸã§æçåå²ç¹ã«ãªããå€ãã®å Žåã return class extends Class
ã§ãæçåå²ç¹ã«ãªããŸãã
ãããæ©èœãããã«ã¯ãããããçš®é¡ã®ããŒããããã¿ãé£ã³è¶ããå¿ èŠããããŸããäžè¬çãªã±ãŒã¹ã§ã¯ç¡æå³ã§ãããããåã·ã¹ãã ã¯ãããã段éã§æŠããŸãã ããã«éèŠãªããšã«ãäžåºŠå®è£ ãããšãä»ã®è€éãªïŒãããå¥å šãªïŒæŠå¿µãå®è£ ããããšãããšãã¯ãã€ã§ããåã·ã¹ãã ã®ãã®ç¡æå³ãªã³ãŒããŒãã¢ã¯ããããçã«æäœããå¿ èŠããããŸãã
éèŠã ãšæããã®1ã€ã®ãŠãŒã¹ã±ãŒã¹ããããããšãã£ãŠïŒãããŠããã®ã¹ã¬ããã§ãæ¢åã®åã·ã¹ãã ã§å¿ èŠãªãã®ãé©åã«è¡šçŸããããã®ä»£æ¿æ¹æ³ã瀺ãããã«äœåºŠãè©ŠããŸããïŒããããå¯äžã®æ£ããããšãæå³ããããã§ã¯ãããŸããããã¹ãããšã¯ãã©ããªç ç²ãæã£ãŠãããªãã®ææ¡ããã¢ãããŒããšäžç·ã«åé²ããããšã§ãã ãã³ã¬ãŒã¿é¢æ°ã®æ»ãåãå«ããä»»æã®ã€ã³ã¿ãŒãã§ã€ã¹ãã¯ã©ã¹ã«ããŒãžã§ããããããã³ã¬ãŒã¿ã䜿çšæ¹æ³ã§äœ¿çšããããšã䞻匵ããå Žåãã©ãã«ã§ãã¢ã¯ã»ã¹ã§ããªããªãããã§ã¯ãããŸããã
@arackaf thisïŒ
function d<T>(Class: new() => T): T & { new (): { blah(): void } } {
return class extends Class {
blah() { }
};
}
extendså¥ã§æ£åžžã«æ©èœããã¯ãã§ãïŒ
class C extends d(S) {
foo() {
this.blah(); // tsc is happy here
}
}
åã·ã¹ãã ã§ã¯ããã«ç°¡åã§ãã§ã«å®çŸ©ãããã»ãã³ãã£ã¯ã¹ã䜿çšããŸãã ããã¯ãã§ã«æ©èœããŠããŸãã ã¹ãŒããŒã¯ã©ã¹ãäœæããã®ã§ã¯ãªãã宣èšãããã¯ã©ã¹ããµãã¯ã©ã¹ã§è§£æ±ºããããšããŠããåé¡ã¯äœã§ããïŒ
@masaeedu
ä»æ¥ã®ãã³ã¬ãŒã¿ã®åäœã¯ãäžè¬çãªã±ãŒã¹ã§ãããå€æŽããããšãæ£åœåãããã®ã§ã¯ãããŸããã
ïŒã¯ã©ã¹ïŒãã³ã¬ãŒã¿ã®äž»ãªçšéã¯ã絶察ã«ãç©æ¥µçã«ãã¯ã©ã¹å
ã®this
ã®å€ãäœããã®æ¹æ³ã§å€æŽããããšã§ãã Reduxã®@connect
ãšMobXã®@observer
ã¯ã©ã¡ããã¯ã©ã¹ãåã蟌ãã§ãæ©èœãè¿œå ãããå
ã®ã¯ã©ã¹ã®æ°ããããŒãžã§ã³ãåãåºããŸãã ãããã®ç¹å®ã®äŸã§ã¯ã this
ã®å®éã®æ§é ã¯å€æŽãããªããšæããŸãïŒ this.props
ã®æ§é ã®ã¿ïŒããããã¯éèŠã§ã¯ãããŸããã
ïŒäžèšã®ã³ã¡ã³ããããããããã«ïŒãã³ã¬ãŒã¿ã䜿çšããŠã¯ã©ã¹ãäœããã®æ¹æ³ã§å€æŽããã®ã¯ãããªãäžè¬çãªãŠãŒã¹ã±ãŒã¹ã§ãïŒã è¯ããæªããã人ã ã¯æ§æäžã®éžæè¢ãå«ãåŸåããããŸã
let Foo = a(b(c(
class Foo {
}
})));
ãšã¯å¯Ÿç §çã«
<strong i="19">@a</strong>
<strong i="20">@b</strong>
<strong i="21">@c</strong>
class Foo {
}
ããŠããã³ã¬ãŒã¿ããããã©ãã
function d (Class){
Class.prototype.blah = function(){
};
}
ãŸã
function d(Class){
return class extends Class {
blah(){ }
}
}
é¢ä¿ãããŸããã ãããã«ãããå€ãã®äººãæ¬åœã«æ±ããŠãããŠãŒã¹ã±ãŒã¹ã¯ãå¿
èŠãªæ³šéã«ãã£ãŠãã©ããªã«äžäŸ¿ã§ãã£ãŠãã function c
ãã¯ã©ã¹C
ãåãããšãTypeScriptã«äŒããããšãã§ããããšã§ãã C & {blah(): void}
ãæã€ã¯ã©ã¹ãè¿ããŸãã
ããããä»æ¥ç§ãã¡ã®å€ãããã³ã¬ãŒã¿ãç©æ¥µçã«äœ¿çšããŠããããšã§ãã ç§ãã¡ã¯æ¬åœã«ããã®æ¯ãèãã®æçšãªãµãã»ãããåã·ã¹ãã ã«çµ±åããããšæã£ãŠããŸãã
ãã³ã¬ãŒã¿ããåã·ã¹ãã ã§ã¯è¿œè·¡ã§ããªãå¥åŠãªããšãå®è¡ã§ããããšã¯ç°¡åã«ããããŸãã 眰éïŒ ããããããã«æ³šéãä»ããæ¹æ³ãå¿ èŠã§ã
<strong i="38">@c</strong>
class Foo {
hi(){ this.addedByC(); }
}
æå¹ã§ãã c
ã«æ°ããå泚éæ§æãå¿
èŠãã©ããããŸãã¯ãããå®çŸããããã«æ¢åã®å泚éæ§æãc
ã§äœ¿çšã§ãããã©ããã¯ããããŸããããäžè¬çãªäœ¿çšæ³ãä¿®æ£ããã ãã§ããã±ãŒã¹ïŒããã³å
ã®ã¯ã©ã¹ã«åœ±é¿ãäžããã«ãšããžããã®ãŸãŸã«ããŠããïŒã¯ãTSãŠãŒã¶ãŒã«ãšã£ãŠå€§ããªæ©æµã«ãªããŸãã
@justinfagnani fyi this
function d<T>(Class: new() => T): T & { new (): { blah(): void } } {
return class extends Class {
blah() { }
};
}
ãçæããŸã
ã¿ã€ã 'typeofïŒå¿åã¯ã©ã¹ïŒ'ã¯ã¿ã€ã 'TïŒïŒnewïŒïŒ=> {blahïŒïŒïŒvoid;}ïŒ'ã«å²ãåœãŠãããšãã§ããŸããã
ã¿ã€ã 'typeofïŒå¿åã¯ã©ã¹ïŒ'ã¯ã¿ã€ã 'T'ã«å²ãåœãŠãããšãã§ããŸããã
TSãã¬ã€ã°ã©ãŠã³ãã§ã ããã€ãã®ãªãã·ã§ã³ãééã£ãŠèšå®ãããŠãããã©ããããããŸããã
ã¹ãŒããŒã¯ã©ã¹ãäœæããã®ã§ã¯ãªãã宣èšãããã¯ã©ã¹ããµãã¯ã©ã¹ã§è§£æ±ºããããšããŠããåé¡ã¯äœã§ããïŒ
ãã³ã¬ãŒã¿ã䜿ãããšããŠããã ãã§ãã ç§ã¯JSã§1幎以äžããããåãã§äœ¿çšããŠããŸã-ç§ã¯TSãè¿œãã€ãããšãæãã§ããŸãã ãããŠãç§ã¯ç¢ºãã«ãµãã¯ã©ã¹åãšçµå©ããŠããŸããã ãã³ã¬ãŒã¿ã¯ãããããã£ãã¡ãœãããè¿œå ããããã«ãå ã®ã¯ã©ã¹ã®ãããã¿ã€ããå€æŽããã ãã®å ŽåããããŸãã ãããã«ãããç®æšã¯TypeScriptã«æ¬¡ã®ããšãäŒããããšã§ãã
<strong i="17">@c</strong>
class Foo {
}
c
ã«ãã£ãŠäœæãããæ°ããã¡ã³ããŒãæã€ã¯ã©ã¹ã«ãªããŸãã
@arackafåã³åæãå€ããŠããŸãã è°è«ã¯ããã«ã€ããŠã§ã¯ãããŸããïŒ
<strong i="8">@a</strong>
<strong i="9">@b</strong>
<strong i="10">@c</strong>
class Foo {
}
察ããïŒ
let Foo = a(b(c(
class Foo {
}
})));
åè
ã䜿çšããŠãã new Foo()
ãé©åã«å
¥åã§ããããšãæåŸ
ããŠããŸãã è°è«ã¯ããã«ã€ããŠã§ãïŒ
<strong i="18">@a</strong>
<strong i="19">@b</strong>
<strong i="20">@c</strong>
class Foo {
fooMember() {
this.aMember(); this.bMember(); this.cMember();
}
}
察ããïŒ
class Foo extends (<strong i="24">@a</strong> <strong i="25">@b</strong> <strong i="26">@c</strong> class { }) {
fooMember() {
this.aMember(); this.bMember(); this.cMember();
}
}
åŸè ã¯åã·ã¹ãã ãå£ãããšãªãæ©èœããŸãã åè ã¯ãç§ããã§ã«èª¬æããããã€ãã®ç¹ã§åé¡ããããŸãã
@masaeeduåè ãæ©èœãããããšãã§ããå¶éããããŠãŒã¹ã±ãŒã¹ã¯æ¬åœã«ãããŸãããïŒ
æ£ç¢ºã«èšããšãåã·ã¹ãã ãåè
ãåŠçããããã«ãTypeScriptãäžèšã®äŸã®a
ã b
ãããã³c
ã«è¿œå ããããã«æ瀺ã§ãã泚éã¯ãããŸãããåŸè
ãšèŠåããã€ããªãïŒ
ããã¯TypeScriptã«ãšã£ãŠãã©ãŒãªé²æ©ãšãªãã§ãããã
@arackafç³ãèš³ãããŸããããtypeãã©ã¡ãŒã¿ãŒãã€ã³ã¹ã¿ã³ã¹åã§ã¯ãªãã³ã³ã¹ãã©ã¯ã¿ãŒåãåç §ããããã«ããå¿ èŠããããŸãã
ããã¯æ©èœããŸãïŒ
type Constructor<T = object> = new (...args: any[]) => T;
interface Blah {
blah(): void;
}
function d<T extends Constructor>(Class: T): T & Constructor<Blah> {
return class extends Class {
blah() { }
};
}
class Foo extends d(Object) {
protected num: number;
constructor(num: number) {
super();
this.num = num;
this.blah();
}
}
ãã³ã¬ãŒã¿ã䜿ãããšããŠããã ãã§ãã
ããã¯ããªãã解決ããããšããŠããåé¡ã§ã¯ãªããããŒãããžãŒã§ãã QïŒããã®ãã³ããŒã§äœãããããšããŠããã®ã§ããïŒãã®ãããªãã®ã§ãã AïŒããã³ããŒã䜿ãã ããã
æå³ããæ¡åŒµæ©èœã§æ°ããã¹ãŒããŒã¯ã©ã¹ãçæã§ããªããšããå®éã®ã±ãŒã¹ãèããŠããŸããïŒ TypeScriptã¯çŸåšããããµããŒãããŠããã®ã§ããããŠç§ãèšã£ãããã«ããã®å Žåãã¯ã©ã¹ã®å éšããã¯ã©ã¹ã®ã¿ã€ãã«ã€ããŠæšè«ããæ¹ãã¯ããã«ç°¡åã§ãã
Mobxã®@observer
ã¢ãããŒã·ã§ã³ã調ã¹ããšãããã¯ã©ã¹ã®åœ¢ç¶ã¯å€æŽãããŠããªãããã§ãïŒ render()
ã©ããããã ããªã®ã§ãã¯ã©ã¹ãã³ã¬ãŒã¿ã§ã¯ãªãã¡ãœãããã³ã¬ãŒã¿ã«ãªããããïŒã
@connect
ã¯ããã³ã¬ãŒã¿ãé©åã«å
¥åããããšã®è€éãã®è¯ãäŸã§ãã @connect
ã¯ãè£
食ãããã¯ã©ã¹ã®ãµãã¯ã©ã¹ãè¿ãããšããã§ããªãããã«èŠããŸãããè£
食ãããã¯ã©ã¹ãã©ãããããŸã£ããæ°ããã¯ã©ã¹ã§ããã¹ã¿ãã£ãã¯ã¯ã³ããŒããããããçµæã¯ã€ã³ã¹ã¿ã³ã¹åŽã®ã€ã³ã¿ãŒãã§ã€ã¹ãç Žæ£ããTSãã»ãšãã©ã®å Žåãã§ãã¯ããªãã¹ã¿ãã£ãã¯åŽãä¿æããŸãã @connect
ã¯å®éã«ã¯ãã³ã¬ãŒã¿ã§ãã£ãŠã¯ãªãããconnectã¯HOCãšããŠäœ¿çšããå¿
èŠãããããã§ããããã¯ããã³ã¬ãŒã¿ãšããŠéåžžã«æ··ä¹±ããããã§ãã
ç§ã¯JSã§1幎以äžãããã楜ãã䜿çšããŠããŸã
ãããš...ããªãã¯æ¬åœã«ããŠããŸããã JSã«ã¯ãã³ã¬ãŒã¿ããããŸããã ããªãã¯ãããããç¹å®ã®å»æ¢ããã以åã®ææ¡ã䜿çšããŠããŸããããããã¯ããŸããŸBabelãšTypeScriptã§ãããã«ç°ãªã£ãŠå®è£ ãããŠããŸãã ä»ã®äŒå Žã§ã¯ããã³ã¬ãŒã¿ãæšæºåããã»ã¹ãç¶ç¶ããããšã䞻匵ããŠããŸãããé²æã¯é ãããŸã 確å®ã§ã¯ãªããšæããŸãã å€ãã®äººããããããè¿œå ããã¹ãã§ã¯ãªãããŸãã¯åã«æ³šéã«ããã¹ãã§ã¯ãªããšäž»åŒµããŠããã®ã§ãã»ãã³ãã£ã¯ã¹ã¯ãŸã 空äžã«ããå¯èœæ§ããããŸãã
ãã³ã¬ãŒã¿ã«å¯Ÿããäžæºã®1ã€ã¯ãã¯ã©ã¹ã®åœ¢ç¶ãå€æŽã§ãããããéçã«æšè«ããã®ãé£ãããšããããšã§ããå°ãªããšããã³ã¬ãŒã¿ã®èœåãå¶éããããã®ããã€ãã®ææ¡ã話ãåãããŠããŸãããããã¯ä»¥åã®ããšã ãšæããŸããææ°ã®ææ¡ã¯ä»æ§èšèªãååŸããŸããã ç§ã¯å人çã«ãè¡åã®è¯ããã³ã¬ãŒã¿ã¯ã¯ã©ã¹ã®åœ¢ç¶ãå€æŽããŠã¯ãªããªãã®ã§ãéçåæã®ç®çã§ã¯ç¡èŠã§ãããšäž»åŒµããŠããŸãã æšæºã®JSã«ã¯ãé¢æ°ã®å®è£ ãäœãããŠããã®ããåæã«äŒããããã®åã·ã¹ãã ããªãããšãå¿ããªãã§ãã ããã
- TSãè¿œãã€ãã®ãåŸ ã¡æãã§ããŸãã
ããã§ã¯ãTypeScriptãã©ã®ããã«é ããŠããã®ãããããŸããã å°ãªããšããäœã®åŸãã«ïŒ ãã³ã¬ãŒã¿ã¯æ©èœããŸãã ã¯ã©ã¹ãåžæã©ããã«åäœããå¥ã®åä»ãJSã¯ãããŸããïŒ
ãã³ã¬ãŒã¿ã¯çŸåšã¹ããŒãž2ã§ãããã»ãŒãã¹ãŠã®JSãã¬ãŒã ã¯ãŒã¯ã§äœ¿çšãããŠããŸãã
@connect
ã®å Žåãreact-reduxã®ããŠã³ããŒãæ°ã¯æã«çŽ250äžåã§ãã å¥ã®æ¹æ³ã§å®è£
ããããããã¶ã€ã³ãã©ãããããããééã£ãŠããããšèãã®ã¯éåžžã«å²æ
¢ã§ãã
ãã³ã¬ãŒã¿ã«ãã£ãŠå°å ¥ãããã¡ãœããã䜿çšããããšãããšãTypeScriptã§åãšã©ãŒãçºçããã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžãè¿œå ãããã¡ãœããã®æ³šéã®æåè¿œå ããŸãã¯ãã³ã¬ãŒã¿ã䜿çšããŠã¯ã©ã¹ãå€æŽããªããªã©ã®åé¿çãå¿ èŠã«ãªããŸãïŒãã³ã¬ãŒã¿ã¯äœ¿çšããªãã§ãã ããïŒã
ãã³ã¬ãŒã¿ãã¯ã©ã¹ã®åœ¢ç¶ãå€æŽããŠããããšãTSã³ã³ãã€ã©ã«æåã§äž¹å¿µã«éç¥ããæ¹æ³ã¯æ¬åœã«ãããŸãããïŒ ãã¶ãããã¯ã¯ã¬ã€ãžãŒã§ãããTSã¯æ°ãããã³ã¬ãŒã¿ãåºè·ããããšã¯ã§ããŸããã§ãã
cïŒãã³ã¬ãŒã¿
ãããŠããã®ã¿ã€ãã®ãã³ã¬ãŒã¿ãã¯ã©ã¹ã«é©çšãããŠããå ŽåïŒãããŠãã®å Žåã®ã¿ïŒãTSã¯ã¯ã©ã¹ãInputïŒ{blahïŒïŒ}åã§ãããšèŠãªããŸããïŒ
æåéãã誰ãããã³ã¬ãŒã¿ã䜿çšã§ããªãããšãç¥ã£ãŠããŸãã ã»ãšãã©ã®äººã¯ãããŒã«ã«ã°ã«ãŒãããã³ã¬ãŒã¿ãå«ãããšãç¥ã£ãŠããŸãã ãã®æçš¿ã¯ãTSãã©ããããããããã³ã¬ãŒã¿ãã¯ã©ã¹å®çŸ©ãå€æŽããŠããããšãåã·ã¹ãã ã«ç解ãããæ¹æ³ã«ã€ããŠã§ãã ããã¯å€ãã®äººã«ãšã£ãŠå€§ããªæ©æµãšãªãã§ãããã
æ£ç¢ºã«èšããšãåã·ã¹ãã ãåè ãšåŸè ãåºå¥ã§ããªãããã«åŠçããããã«ãTypeScriptãäžèšã®äŸã®aãbãcã«è¿œå ããããã«æ瀺ã§ãã泚éã¯ãããŸãããïŒ
ã¯ãã Foo
ã®åœ¢ç¶ã宣èšããã®ã¯éåžžã«ç°¡åã§ããå¿
èŠãªã®ã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžã䜿çšããããšã ãã§ãã ããªãã¯ãã ããå¿
èŠããããŸãïŒ
interface Foo extends <whateverextramembersiwantinfoo> { }
<strong i="9">@a</strong>
<strong i="10">@b</strong>
<strong i="11">@c</strong>
class Foo {
/* have fun */
}
ä»ã®ãšãããè¿ããããã®ã«å¯Ÿå¿ãããã©ã¡ãŒã¿åãããã¿ã€ãããšã¯ã¹ããŒãããããã«äœ¿çšããŠãããã³ã¬ãŒã¿ã©ã€ãã©ãªãæåŸ
ããå¿
èŠããããŸãããŸãã¯ãè¿œå ããã¡ã³ããŒãèªåã§å®£èšããå¿
èŠããããŸãã ïŒ6606ãååŸããå Žåã¯ã interface Foo extends typeof(a(b(c(Foo))))
ãå®è¡ã§ããŸãã
ãã³ã¬ãŒã¿ã«ãã£ãŠå°å ¥ãããã¡ãœããã䜿çšããããšãããšãTypeScriptã§åãšã©ãŒãçºçããã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžãè¿œå ãããã¡ãœããã®æ³šéã®æåè¿œå ããŸãã¯ãã³ã¬ãŒã¿ã䜿çšããŠã¯ã©ã¹ãå€æŽããªããªã©ã®åé¿çãå¿ èŠã«ãªããŸãïŒãã³ã¬ãŒã¿ã¯äœ¿çšããªãã§ãã ããïŒã
ãã³ã¬ãŒã¿ã§çŽ¹ä»ãããã¡ã³ããŒã«äŸåããªãå Žåã¯ãäœæããŠããã¯ã©ã¹ãè£ é£Ÿããããã§ãªãå Žåã¯ãè£ é£Ÿãããã¯ã©ã¹ãæ¡åŒµãããªãã·ã§ã³ã«ã€ããŠã¯èšåããŠããŸããã ããããå°ãªããšããã³ã¬ãŒã¿ã䜿çšããæ¹æ³ã§ãã
çŸåšäœ¿çšããŠããã©ã€ãã©ãªã®ã³ãŒãã¹ãããããæããŠãã ããããããåé¡ã§ãã
ç³ãèš³ãããŸããããæåŸã®ã³ã¡ã³ãã«ã¯åŸããŸããã§ãããããã®åã®ã³ã¡ã³ãã¯ãã€ã³ã¿ãŒãã§ã€ã¹ãããŒãžãããŠããããŸãã«ç§ãåé¿ããŠããæ¹æ³ã§ãã
çŸåšãç§ã®ãã³ã¬ãŒã¿ã¯Typeããšã¯ã¹ããŒãããå¿ èŠããããŸãããŸãããã³ã¬ãŒã¿ã«ãã£ãŠæ°ããã¡ã³ããŒãè¿œå ãããŠããããšãTSã«ç€ºãããã«ã衚瀺ãããšããã«ã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžã䜿çšããŸãã å€ãã®äººãåæããŠããã®ã¯ããã®è¿œå ãããå®åæãæšãŠãèœåã§ãã
@arackafããããããªããæ¬åœã«æãã§ããã®ã¯ã宣èšã®ããŒãžãé¢æ°ã®åŒæ°ã®ã³ã³ããã¹ãåãšçžäºäœçšããæ¹æ³ã§ãã
ãã¡ããã ã¯ã©ã¹ã§ãã³ã¬ãŒã¿ã䜿çšã§ããããã«ãããã®ã§ãããæŠå¿µçã«ã¯ããã³ã¬ãŒã¿ã®å®çŸ©æ¹æ³ã«åºã¥ããŠãã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžãå®è¡ããè£ é£Ÿãããã¯ã©ã¹ã«è¿œå ã®ã¡ã³ããŒãè¿œå ã§ããããã«ããŸãã
ãã³ã¬ãŒã¿ã«æ³šéãä»ããŠãããå®çŸããæ¹æ³ãããããŸããããããŸãæ°ã«ãªããŸãããå°æ¥ã®TSããŒãžã§ã³ã§åœ±é¿ãäžããæ§æãããã°ãä¿¡ããããªãã»ã©å¹žãã«ãªããŸã:)
ãã³ã¬ãŒã¿ã¯çŸåšã¹ããŒãž2ã§ãããã»ãŒãã¹ãŠã®JSãã¬ãŒã ã¯ãŒã¯ã§äœ¿çšãããŠããŸãã
ãããŠã圌ãã¯ã¹ããŒãž2ã«éãããéåžžã«ãã£ãããšåããŠããŸãã ç§ã¯ãã³ã¬ãŒã¿ãå®çŸãããããšæã£ãŠããŸãããã³ã¬ãŒã¿ã®ç§»åãã©ã®ããã«æ¯æŽã§ããããèããŠããŸãããããã§ã確å®ã§ã¯ãããŸããã ããã»ã¹ã«åœ±é¿ãåãŒããå察ãããã泚éã«éå®ãããããå¯èœæ§ã®ãã人ã ãä»ã§ãç¥ã£ãŠããŸããã圌ããå¹²æžããããšã¯ãªããšæããŸãã çŸåšã®ã³ã³ãã€ã©ãã³ã¬ãŒã¿ã®å®è£ ãJSã§ã¯ãªããšããç§ã®äž»åŒµã¯æ£ããã§ãã
@connectã«é¢ããŠã¯ãreact-reduxã¯æã«çŽ250äžããŠã³ããŒãã«ãªã£ãŠããŸãã å¥ã®æ¹æ³ã§å®è£ ããããããã¶ã€ã³ãã©ãããããããééã£ãŠããããšèãã®ã¯éåžžã«å²æ ¢ã§ãã
ç§ãå²æ ¢ãšåŒã¶ãããªå人çãªæ»æã¯æ§ããŠãã ããã
connect()
é¢æ°ã¯HOCã®ããã«èŠããŸãããã³ã¬ãŒã¿ã«ãã£ãŠå°å ¥ãããã¡ãœããã䜿çšããããšãããšãTypeScriptã§åãšã©ãŒãçºçããã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžãè¿œå ãããã¡ãœããã®æ³šéã®æåè¿œå ããŸãã¯ãã³ã¬ãŒã¿ã䜿çšããŠã¯ã©ã¹ãå€æŽããªããªã©ã®åé¿çãå¿ èŠã«ãªããŸãïŒãã³ã¬ãŒã¿ã¯äœ¿çšããªãã§ãã ããïŒã
ãã³ã¬ãŒã¿ããŸã£ãã䜿çšããªãããšãææ¡ããŠããã ãã§ã¯ãããŸããã @ masaeeduã¯ããããã¿ã€ããã¿ã€ãã»ãŒããªæ¹æ³ã§å€æŽããç®çã§ãç¶æ¿ãšããã¯ã¹ã€ã³ã¢ããªã±ãŒã·ã§ã³ãšããæ¢åã®ã¡ã«ããºã ããããšèšã£ãŠãããšæããŸãã d
ã®äŸãããã¯ã¹ã€ã³ãšããŠäœ¿çšããã®ã«é©ããŠããªãçç±ãå°ããããšããŠããã®ã§ããããã³ã¬ãŒã¿ã䜿çšããããšãã以å€ã¯çããŸããã§ããã
ããã§ãããšæããŸãããäŒè©±ãããªãæ¹å€çã«å¶éããŠããããã§ãã®ã§ããŸããèŸåãããŸãã
@justinfagnaniç§ã話ããŠãã
import {connect} from 'react-redux'
connect
äžèšã®ããã«ãã¯ã©ã¹ïŒã³ã³ããŒãã³ãïŒãåã蟌ãã§å¥ã®ã¯ã©ã¹ãåãåºãé¢æ°ããããŸãã
çŸåšãBabelãšTypeScriptã®äž¡æ¹ã§ããã®ããã«connect
ã䜿çšãããªãã·ã§ã³ããããŸã
class UnConnectedComponent extends Component {
}
let Component = connect(state => state.foo)(UnConnectedComponent);
ãŸãã¯ãã®ããã«
@connect(state => state.foo)
class Component extends Component {
}
ç§ã¯ããŸããŸåŸè ã奜ã¿ãŸãããããªããä»ã®èª°ããåè ã奜ããªããããããŠãã ããã å€ãã®éãããŒãã«éããŠããŸãã ç§ãåæ§ã«å¥œãã§ã
<strong i="19">@mappable</strong>
<strong i="20">@vallidated</strong>
class Foo {
}
以äž
let Foo = validated(mappable(class Foo {
}));
ãŸã
class Foo extends mixin(validated(mappable)) {
}
//or however that would look.
ãã³ã¬ãŒã¿ã䜿çšããçç±ãæ確ã ãšæã£ããããšãã£ãŠãããªãã®è³ªåã«æ瀺çã«çããããã§ã¯ãããŸããããæ瀺çã«è¿°ã¹ãŸãã人éå·¥åŠãšæ§æãã³ã¬ãŒã¿ãæäŸãããã®ã奜ã¿ãŸãã ãã®å šäœã®ã¹ã¬ããã¯ããã³ã¬ãŒã¿ãåé¡ã®ã¯ã©ã¹ãã©ã®ããã«å€æŽããŠããããTSã«äŒããæ©èœãååŸããããšããŠãããããã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžã®ãããªå®åæã¯å¿ èŠãããŸããã
OPãæã«èšã£ãããã«ãç§ãã¡ã¯ãã 欲ãã
declare function Blah<T>(target: T): T & {foo: number}
<strong i="31">@Blah</strong>
class Foo {
bar() {
return this.foo; // Property 'foo' does not exist on type 'Foo'
}
}
new Foo().foo; // Property 'foo' does not exist on type 'Foo'
ãã åãããã«ã ãã®ç¹å®ã®æ§æã«ä»ã®éžæè¢ãååšãããšããäºå®ã¯ãæçœã§ãããéèŠã§ã¯ãããŸããã JS / TSã³ãã¥ããã£ã®å€ãããã®ç¹å®ã®æ§æãå«ã£ãŠãããšããäºå®ããæçœã§éèŠã§ã¯ãããŸããã
TSããå¶éãããŠããŠãããã®æ§æãæ©èœãããæ¹æ³ãæäŸã§ããã°ãèšèªãšã³ãã¥ããã£ã«å€§ããªã¡ãªããããããŸãã
@arackaf connect
ã䜿çšãããšã this
ã®è¿œå ã¡ã³ããŒã«ã¢ã¯ã»ã¹ããå¿
èŠãããããšã«ã€ããŠèšåããŠããŸããã AFAICTãã³ã³ããŒãã³ãã®å®è£
ã¯connect
ã®æ©èœã«å®å
šã«äŸåããªãã¯ãã§ãããç¬èªã®props
ãšstate
ã®ã¿ã䜿çšããŸãã ãããã£ãŠããã®æå³ã§ã connect
ã®èšèšæ¹æ³ã¯ã @ justinfagnaniã®ãã³ã¬ãŒã¿ã®äœ¿çšæ³ãšããªãã®äœ¿çšæ³ãããäžèŽããŠããŸãã
ããŸãã æ€èš
@connect(state => state.stuffThatSatisfiesPropsShape)
class Foo extends Component<PropsShape, any> {
}
ãããåŸã§
<Foo />
ããã¯æå¹ãªã¯ãã§ã-PropsShapeã®å°éå
·ã¯Reduxã¹ãã¢ããæ¥ãŠããŸãããTypeScriptã¯Fooã®å
ã®å®çŸ©ããå€ããŠããããããããèªèããŠããŸããããã®ãããå°éå
·ãèŠã€ãããªãããã«ãšã©ãŒãçºçãã any
ãšããŠãã£ã¹ãããå¿
èŠããããŸãã
ããããæ確ã«ããããã«ãå ã OPã«ãã£ãŠäžããããäžèšã®2çªç®ã®ã³ã¡ã³ãã§è€è£œãããæ£ç¢ºãªãŠãŒã¹ã±ãŒã¹ã¯ãã³ãŒãããŒã¹ã§éåžžã«äžè¬çã§ããããã®å€èŠ³ãããä»ã®å€ãã®äººãåæ§ã§ãã ç§ãã¡ã¯æåéã次ã®ãããªãã®ã䜿çšããŸã
<strong i="6">@validated</strong>
<strong i="7">@mappable</strong>
class Foo {
}
TypeScriptãæºããããã«ãã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžãè¿œå ããå¿ èŠããããŸãã ãã®ã€ã³ã¿ãŒãã§ã€ã¹ããã³ã¬ãŒã¿å®çŸ©ã«ééçã«ããŒãžããæ¹æ³ããããšäŸ¿å©ã§ãã
ããã§èŒªã«ãªã£ãŠãããŸãã Foo
ã®ã¿ã€ãã¯connect
ã®ãªã¿ãŒã³ã¿ã€ãã§ãªããã°ãªããªãããšã«åæããŸãã ç§ãã¡ã¯ããã«ã€ããŠå®å
šã«åæããŠããŸãã
ç°ãªãã®ã¯ã Foo
å
ã®ã¡ã³ããŒãã this
ããã³ã¬ãŒã¿ãªã¿ãŒã³ã¿ã€ããšãå
ã®Fooãã®ååž°çãªèåã§ãããã®ããã«èŠããããå¿
èŠããããã©ããã§ãã ãã®ãŠãŒã¹ã±ãŒã¹ã¯ç€ºããŠããŸããã
ç°ãªãã®ã¯ãFooå ã®ã¡ã³ããŒããããããã³ã¬ãŒã¿ãªã¿ãŒã³ã¿ã€ããšãå ã®Fooãã®ããçš®ã®ååž°çãªèåã§ãããã®ããã«èŠããããå¿ èŠããããã©ããã§ãã ãã®ãŠãŒã¹ã±ãŒã¹ã¯ç€ºããŠããŸããã
ç§ã¯æã£ãŠããã äžèšã®ç§ã®ã³ã¡ã³ããåç §ããŠãã ãããããã«ã€ããŠã¯ãOPã®å ã®ã³ãŒããåç §ããŠãã ããã ããã¯éåžžã«äžè¬çãªãŠãŒã¹ã±ãŒã¹ã§ãã
connect
ããã³ã³ããŒãã³ãå
ã§ã¢ã¯ã»ã¹ããããšãæåŸ
ããŠãããããã¿ã€ãã«äœãè¿œå ããããæããŠãã ããã çãããäœããªããã®å Žåã¯ããŸã£ããé¢ä¿ããªãããã connect
ãå床衚瀺ããªãã§ãã ããã
@masaeeduã¯ååã«å
¬å¹³ã§ãåæããŸãã ç§ã¯äž»ã«ããã³ã¬ãŒã¿ãå
ã®ã¯ã©ã¹ãå€æŽããŠã¯ãªããªãã connect
ã®èšèšãäžååã§ãããªã©ã @ justinfagnaniã®äž»åŒµã«å¿ããŠããŸããã
ä»ã®ãªãã·ã§ã³ãããŸããŸååšãããšããäºå®ã«ãããããããç§ã¯ç§ãšä»ã®å€ãã®äººãããŸããŸå¥œãæ§æã瀺ããŠããã ãã§ããã
ãã®å Žåãã¯ããã¯ã©ã¹ãåã蟌ãã§ãè£ é£Ÿãããã¯ã©ã¹å ã§äœ¿çšãããæ°ããã¡ãœããã䜿çšããŠæ°ããã¯ã©ã¹ãåãåºã人æ°ã®ããnpmã©ã€ãã©ãªãç¥ããŸããã ããã¯ãç§ãä»ã®äººãç§ãã¡èªèº«ã®ã³ãŒãã§ãç§ãã¡èªèº«ã®ããã¯ã¹ã€ã³ãå®è£ ããããã«é »ç¹ã«è¡ãããšã§ãããnpmã®äŸã¯å®éã«ã¯ãããŸããã
ãããããããäžè¬çãªãŠãŒã¹ã±ãŒã¹ã§ããããšã«ç°è«ã¯ãããŸãããã
@arackafãããã @connect
ã«ãã£ãŠå°å
¥ãããthis
ã®ã¡ã³ããŒã«ã¢ã¯ã»ã¹ããŠããªãããã§ã¯ãããŸããã å®éãç§ã¯ãã®æ£ç¢ºãªã¹ãããããããªã確信ããŠããŸãïŒ
@connect(state => state.stuffThatSatisfiesPropsShape)
class Foo extends Component<PropsShape, any> {
render(){
this.props.stuffFromPropsShape // <----- added by decorator
}
}
ä»æ¥ã®TypeScriptã§ã¯åé¡ãªãã³ã³ãã€ã«ãããŸãã 貌ãä»ããã¹ããããã¯ãèŠæ±ããŠããæ©èœãšã¯äœã®é¢ä¿ããããŸããã
@ masaeedu-ããããªãã-ç§ã¯èªåãééã£ãŠããããšã«æ°ã¥ãããã®ã³ã¡ã³ããåé€ããŸããã ããããããªããããªãã®æéãç¡é§ã«ããã®ãé²ãã®ã«ååãªéãã§ã¯ãããŸãã:(
@arackafãã¿ãŒã³ãã©ãã»ã©äžè¬çãã¯ããããŸãããå人çã«ã¯ãèªåã§äœ¿çšããããšãã䜿çšããã©ã€ãã©ãªã䜿çšããããšããããŸããã Angular 2ããã°ãã䜿ã£ãŠããã®ã§ã人çã§ãã³ã¬ãŒã¿ã䜿ã£ãããšããªãããã§ã¯ãããŸããã ãããããã³ã¬ãŒã¿ã§çŽ¹ä»ããããã³ã¬ãŒã¿ã®ã¡ã³ããŒã«ã¢ã¯ã»ã¹ã§ããªãããšãåé¡ãšãªãã©ã€ãã©ãªã䜿çšããå ·äœçãªäŸãæ±ããŠããçç±ã§ãã
ã¯ã©ã¹ã®ã¡ã³ããŒãthis
ã®äœããæåŸ
ããå Žåã¯åžžã«ãã¯ã©ã¹ã®æ¬äœãŸãã¯ã¯ã©ã¹ã®extends
å¥ã«èŠä»¶ãæºãããã®ãååšããå¿
èŠããããŸãã ããã¯ããã³ã¬ãŒã¿ã䜿çšããå Žåã§ããåžžã«æ©èœããŠããæ¹æ³ã§ãã ã¯ã©ã¹ãäŸåããæ©èœãè¿œå ãããã³ã¬ãŒã¿ãããå Žåãã¯ã©ã¹ã¯ãã³ã¬ãŒã¿ãè¿ããã®ãæ¡åŒµããå¿
èŠãããããã®éã§ã¯ãããŸããã ããã¯åžžèã§ãã
ãªããããåžžèãªã®ãããããŸããã ããã¯çŸåšã®ã³ãŒãããŒã¹ã®ã³ãŒãã§ãã ã¯ã©ã¹ã®ãããã¿ã€ãã«ã¡ãœãããè¿œå ãããã³ã¬ãŒã¿ããããŸãã TypeScriptããšã©ãŒã«ãªããŸãã åœæãç§ã¯ãã®å®£èšãããã«æããŸããã ã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžã䜿çšããããšãã§ããŸãã
ããããäœã䜿çšããªããšããã§ãããã TypeScriptã«ãããã®ãã³ã¬ãŒã¿ã¯ãé©çšãããã¯ã©ã¹ã«ãã®ã¡ãœãããè¿œå ããŸããã¯ã©ã¹å
ã®this
ã«ãã¢ã¯ã»ã¹ãèš±å¯ããŸãããšäŒããããšãã§ããã°æ¬åœã«çŽ æŽãããã§ãããã
ãã®ã¹ã¬ããã®ä»ã®å€ãã®äººãåæ§ã«ãã³ã¬ãŒã¿ã䜿çšããŠããããã«èŠããã®ã§ããããæ©èœããªãããšã¯åžžèã§ã¯ãªããããããªããšèããŠããã ããã°å¹žãã§ãã
@arackafãããããªãã¯export class SearchVm extends (@mappable({...}) class extends SearchVmBase {})
ãããŠããã¯ãã§ãã ãããã³ã°å¯èœæ§ã«äŸåããã®ã¯SearchVm
ã§ããããã®éã§ã¯ãããŸããã
ãšã¯ã¹ããŒãã¯ã©ã¹SearchVmextendsïŒ@mappableïŒ{...}ïŒã¯ã©ã¹extends SearchVmBase {}ïŒ
ãã®ã¹ã¬ããã®èŠç¹ã¯ããã®ãããªå®åæãé¿ããããšã§ãã ãã³ã¬ãŒã¿ã¯ããã®ãããªããšãããªããã°ãªããªããããã¯ããã«åªããDXãæäŸããŸãã ããããããç§ãæã£ãŠãããããªã³ãŒããæžãããšãéžãã ã®ã«ã¯çç±ããããŸãã
ãã®ã¹ã¬ãããžã®ã³ã¡ã³ããèªãã ããä»ã®å€ãã®äººãããåçŽãªãã³ã¬ãŒã¿æ§æã䜿çšããããšããŠããããšã確信ããŠãç§ãã¡ãããã¹ããããšããåžžèããªã©ãåèããããšãé¡ã£ãŠããŸãã
ããªããæããã®ã¯ãç¹ã«ãã³ã¬ãŒã¿ãšã¯äœã®é¢ä¿ããããŸããã ããªãã®åé¡ã¯ããã¡ãã£ãšTypeScriptãããªããäœãç¥ããªããã®æ§é ã«äœããèµ·ãã£ãŠãããããã«ã€ããŠãã¹ãŠããªãã«è©±ãããŠãã ããããšèšãããã®TypeScriptã®ã¡ã«ããºã ãçŸåšããŸãã«ãå¶éãããŠãããšããããšã§ãã çŸåšãã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžãããããŸããããé¢æ°ãã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžãåŒæ°ã«é©çšã§ããããã«ããå¿ èŠããããŸããããã¯ããã³ã¬ãŒã¿ãšã¯ç¹ã«é¢ä¿ãããŸããã
çŸåšãã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžãããããŸããããé¢æ°ãã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžãåŒæ°ã«é©çšã§ããããã«ããå¿ èŠããããŸããããã¯ããã³ã¬ãŒã¿ãšã¯ç¹ã«é¢ä¿ãããŸããã
Okã ãã£ããã ã å¥ã®å·ãéããŠã»ããã§ããããããšããã®å·ã®ååãå€æŽãããã§ããïŒ
@arackafå¯äžã®ããã€ã©ãŒãã¬ãŒããã¯ãç§ãclass { }
ãæã£ãŠãããšããäºå®ã§ããããã¯ã aïŒäœ¿çšãããã³ã¬ãŒã¿ã®æ°ã«é¢ä¿ãªããåºå®ããã7æåã§ããbïŒãã³ã¬ãŒã¿ãïŒãŸã ïŒã§ããªããšããäºå®ã®çµæã§ãã ïŒä»»æã®ã¯ã©ã¹ãè¿ãåŒã«é©çšãããŸããcïŒç§ã¯ããªãã®å©çã®ããã«ãã³ã¬ãŒã¿ãç¹ã«äœ¿çšãããã£ãã®ã§ã ãã®ä»£æ¿ã®å®åŒåïŒ
export class SearchVm extends mappable({...})(SearchVmBase)
{
}
ããªããæåã«ãã£ãŠããããšãããåé·ã§ã¯ãããŸããã
Okã ãã£ããã ã å¥ã®å·ãéããŠã»ããã§ããããããšããã®å·ã®ååãå€æŽãããã§ããïŒ
å¥ã®åé¡ãè¯ãã§ãããã
ããªããæåã«ãã£ãŠããããšãããåé·ã§ã¯ãããŸãã
ãã以äžåé·ã§ã¯ãããŸããããå€ãã®äººããã®æ§æãåã«å«ã£ãŠãããšããäºå®ãèæ ®ããŠããã ããããšæããŸãã è¯ããæªãããå€ãã®äººãDXãã³ã¬ãŒã¿ãæäŸãããã®ã奜ã¿ãŸãã
å¥ã®åé¡ãè¯ãã§ãããã
ææ¥å ¥åããã³ã³ããã¹ããšããŠããã«ãªã³ã¯ããŸãã
ãããä»ããŠäœæ¥ãæ¯æŽããŠããã ãããããšãããããŸã:)
ç§ãå ¥ããããããªããªãã @ masaeeduç§ã¯ãã®å£°æã«åæããŸããïŒ
ããªããæããã®ã¯ãç¹ã«ãã³ã¬ãŒã¿ãšã¯äœã®é¢ä¿ããããŸããã ããªãã®åé¡ã¯ããã¡ãã£ãšTypeScriptãããªããäœãç¥ããªããã®æ§é ã«äœããèµ·ãã£ãŠãããããã«ã€ããŠãã¹ãŠããªãã«è©±ãããŠãã ããããšèšãããã®TypeScriptã®ã¡ã«ããºã ãçŸåšããŸãã«ãå¶éãããŠãããšããããšã§ãã çŸåšãã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžãããããŸããããé¢æ°ãã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžãåŒæ°ã«é©çšã§ããããã«ããå¿ èŠããããŸããããã¯ããã³ã¬ãŒã¿ãšã¯ç¹ã«é¢ä¿ãããŸããã
確ãã«ãTypeScriptã¯ãã¯ã©ã¹ãã³ã¬ãŒã¿ã®æ»ãåã調ã¹ãŠãå€æŽãããã¯ã©ã¹ãã©ã®åã§ããããå€æã§ããŸãã ãåŒæ°ã«ããŒãžããã€ã³ã¿ãŒãã§ãŒã¹ãé©çšãããå¿ èŠã¯ãããŸããã ã§ããããç§ãèŠãŠããããã«ãããã¯å®å šã«ãã³ã¬ãŒã¿ãšé¢ä¿ããããŸãã
ãŸããæ¥ç¶ãããã³ã³ããŒãã³ãããã¯ãå°éå ·ãå¿ èŠãšããªãããšãTypeScriptãç¥ããªãå Žåã¯ãReactãšTypeScriptã§Reduxã䜿çšããããšãããããã1ã€ã®åŽé¢ã§ãã
@codeandcatsããã¯ããŸãæ©èœããŸããïŒ https://github.com/Zalastax/openschedule/blob/335ee3834122da7f65ba35f89d8fd737309fc4fb/src/components/week-selection/index.tsx https://github.com/Zalastax/openschedule/blob/335ee3834122da7f65ba35f89d8fd737 .tsx
@codeandcatsã¹ã¬ãããå§ãŸã£ãŠä»¥æ¥ãç§ã¯ãããšèŒªã«ãªã£ãŠããŠãæ¬åœã«ãããããããããšãã§ããŸããã åã®è°è«ã泚ææ·±ãèŠãŠãå®éã«ç§ã@arackafã«å察ããŠããããšãç解ããŠã¿ãŠãã ããã
<strong i="8">@bar</strong> class Foo { }
ãå®è¡ããå Žåã Foo
ã®ã¿ã€ãã¯bar
ã®ãªã¿ãŒã³ã¿ã€ãã§ããå¿
èŠãããããšã«åæããŸãã Foo
this
ãäœããã®åœ¢ã§åœ±é¿ãåããããšã«åæããŸããã connect
ã䜿çšããããšã¯ãããã§ã®è«ç¹ãšã¯ãŸã£ããé¢ä¿ãããŸããã connect
ã¯ãè£
食ãããã³ã³ããŒãã³ãããããã¿ã€ãã«è¿œå ããã¡ã³ããŒãèªèããŠäœ¿çšããããšãæåŸ
ããŠããªãããã§ãã
@masaeeduã«äžæºãæããŠããããšã¯ç解ã§ããŸãããéå»48æéã«ããã£ãŠç§ãè°è«ããã©ããŒããŠããªããšããæèŠãç©æ¥µçã«è¡šæããŠããªããšããçç±ã ãã§ãç§ãè°è«ããã©ããŒããŠããªããšæã蟌ãŸãªãã§ãã ãããç§ã«èŠäžãã®ä»²éãæããŸãªãã§ãã ããã
ç§ãç解ããŠããããã«ããã³ã¬ãŒããããã¯ã©ã¹ã®å éšã§ã¯ããã³ã¬ãŒã¿ã«ãã£ãŠããèªäœã«å ããããçªç¶å€ç°ã«ã€ããŠã¯ç¥ããªãã¯ãã§ãããå€éšã§ã¯ç¥ã£ãŠããå¿ èŠããããŸãã ç§ã¯ããã«åæããŸããã @arackafãã¯ã©ã¹å ã§å€æŽãããããŒãžã§ã³ã確èªããå¿ èŠããããšèãããšããäºå®ã¯ãç§ã®ã³ã¡ã³ãã®ãã€ã³ããè¶ ããŠããŸãã
ãããã«ãããTypeScriptã¯ããã³ã¬ãŒã¿é¢æ°ã«ãã£ãŠè¿ãããåãã¯ã©ã¹ã®ä¿¡é Œã§ããæ å ±æºãšããŠäœ¿çšã§ããŸãã ãããã£ãŠãããã¯ãã³ã¬ãŒã¿ã®åé¡ã§ãããããªããææ¡ãããããªããã€ãã®æ°ããå¥åŠãªåŒæ°ã®çªç¶å€ç°æ©èœã§ã¯ãããŸãããããã¯ãæ£çŽãªãšãããã¹ãããŒãã³ã®è©Šã¿ã®ããã«èãããŸãã
@Zalastaxã¯ããã³ã¬ãŒã¿ãšããŠã§ã¯ãªããé¢æ°ãšããŠãã³ã¬ãŒã¿é¢æ°ã䜿çšããŠããŸãã è€æ°ã®ãã³ã¬ãŒã¿ãé©çšããå¿ èŠãããå Žåã¯ããããããã¹ãããå¿ èŠããããŸããããã¯ãæè¡çã«ã¯ãã¯ãåé·ã§ã¯ãããŸããããæ§æçã«ã¯å¿«é©ã§ã¯ãããŸãããç§ãäœãæå³ãããç¥ã£ãŠããŸããïŒ
軜èãªã©
ãã€ãºã
@arackafãã¯ã©ã¹å ã§å€æŽãããããŒãžã§ã³ã確èªããå¿ èŠããããšèãããšããäºå®ã¯ãç§ã®ã³ã¡ã³ãã®ãã€ã³ããè¶ ããŠããŸãã
ããã¯ããªããå¿çããŠãã段èœã®äžå¿ç¹ãªã®ã§ãããªããäœãä»ã®ããšã«ã€ããŠè©±ããŠãããªããããã¯ç¡é¢ä¿ã§ãã @arackafãæãã§ããã®ã¯ã倧ãŸãã«èšã£ãŠãé¢æ°ã®åŒæ°ã«ããŒãžããã€ã³ã¿ãŒãã§ãŒã¹ã§ãã ããã¯ããã³ã¬ãŒã¿ã«äŸåããªãæ©èœã«ãã£ãŠããé©åã«å¯ŸåŠãããŸãã ããªããæãã®ã¯ïŒæããã«ç§ãæããã®ãšåãã§ãïŒãTypeScriptã®ãã°ãä¿®æ£ããããšã§ãã <strong i="12">@foo</strong> class Foo { }
ã¯Foo
ã«å¯ŸããŠconst Foo = foo(class { })
ãšåãå眲åã«ãªããŸããã
ç§ãç解ããŠããããã«ããã³ã¬ãŒããããã¯ã©ã¹ã®å éšã§ã¯ããã³ã¬ãŒã¿ã«ãã£ãŠããèªäœã«å ããããçªç¶å€ç°ã«ã€ããŠã¯ç¥ããªãã¯ãã§ãããå€éšã§ã¯ç¥ã£ãŠããå¿ èŠããããŸãã ç§ã¯ããã«åæããŸãã
ç§ãã¡ãåæããŠããããšã«ã€ããŠè©±ãããšã«ãããããã®åã«ãç§ã¯ãã®å£°æã«åæããŸããããšèšã£ãå Žåãããªãã¯ãã æéãç¡é§ã«ããŠããã ãã§ãã
ãã®å¡©ã§ãã©ã€ãããããããããŸããïŒ
ããããªãã»ã©ãããªããããªãã®ä»²éãã²ããã«ãããšããããã¯çŽ æŽãããã§ããããã人ã ãããªããããã«åŒãäžãããªãã°ãããã¯éšé³ã§ãã
@arackafãææ¡ãããã®ãå®è£ ããããã«ããªããåŒæ°ã®çªç¶å€ç°ãã®æŠå¿µãå¿ èŠãªã®ãããããŸããã
@arackafã«åæãããã©ããã«é¢ä¿ãªããã©ã¡ãã®æ¹æ³ã§ããTypeScriptã¯ãç§ã®è¬èãªæèŠã§ã¯ããã³ã¬ãŒã¿ã®çµæããå®éã®åãåçŽã«æšæž¬ã§ããŸãã
ããªãã軜èãããŠãããšæããå Žåã¯ãè©«ã³ããŸãã æå³ã¯ããªããã«é£ããŠè¡ãããšã§ãã
å®éã誰ããèš±ãããå¯èœæ§ã®ãã巚倧ãªãšããšãã®ãªãã¹ã¬ãã
ã¹ããã³ã°ã ããªããæ°ã¥ããŠããªãã®ã¯ãŸã ããªãæãããªã®ã§ãç§ã¯ãããæ¯æããŸã
詳现ã®èª€è§£ã«åºã¥ããŠç§ãšãæèŠãåããªãã
ç§ã®ç«å Žã
ããšãã°ãã€ã³ã¿ãŒãã§ã€ã¹ãé¢æ°ã«ããŒãžãããçç±ã«ã€ããŠã®è³ªå
è°è«ã¯ã¢ãã ã®åé¡ã解決ããŸãé¢é£ãããã®ãèŠãããšã«ãã£ãŠæãããçããããŸã
Adamãšã®è©±ãåãã§ã圌ã¯ãã§ã«ã€ã³ã¿ãŒãã§ã€ã¹ã®ããŒãžã䜿çšããŠãããšè¿°ã¹ãŠããŸãã
ããããå宣èšãµã€ãã§ãããè¡ããªããã°ãªããªãã®ã¯é¢åã§ãã
ç§ã¯ããã®ãã¹ãŠã®æè¡çåŽé¢ãæã¡è² ãããããšæããŸãã ç§
ã¹ã¬ããã察人é¢ä¿ã®äºãã«æ¯é
ãããããšãæãŸãªãã®ã§ãããã¯
ç§ã®æåŸã®æçš¿ã«ãªããŸãã
確ãã«ããã³ã¬ãŒã¿ã«ã¯2ã€ã®ãã°ããããŸããreturnã¿ã€ããå°éãããªãããšãšãã¯ã©ã¹ã®å
éšã§è¿œå ãããã¡ã³ããŒãå°éãããªãããšã§ãïŒã¯ã©ã¹å
ã®this
ïŒã ãããŠãã¯ããåè
ã¯ããç°¡åã«åé¿ã§ããã®ã§ãç§ã¯åŸè
ã«ãã£ãšé¢å¿ããããŸãã
ããã§å¥ã®ã±ãŒã¹ãéããŸããïŒ https ïŒ//github.com/Microsoft/TypeScript/issues/16599
ã¿ãªãããé±æ«ã«ãã®äŒè©±ãéããŸããããããããä»ããäŒè©±ãåéããçç±ã¯ããŸããããŸããã ãããããã®çš®ã®è°è«ã®çã£åªäžã§ãåå ãããã¹ãŠã®äººã¯éåžžãåæãæã£ãŠããããšãçããã«æãåºãããããšæããŸãã æ¬æãè¡šããå£èª¿ãä¿ã€ããšã¯ãäŒè©±ãæ確ã«ããå°ãã®ã«åœ¹ç«ã¡ãæ°ããè²¢ç®è ãè²æããããšãã§ããŸãã ãããè¡ãã®ã¯å¿ ãããç°¡åã§ã¯ãããŸãããïŒç¹ã«ã€ã³ã¿ãŒããããèªè ã«èª¿æ§ãä»»ããŠããå ŽåïŒãå°æ¥ã®ã·ããªãªã§ã¯éèŠã ãšæããŸãã ð
ããã®ç¶æ³ã¯ã©ãã§ããïŒ
@ alex94puchadesã¯ãŸã ã¹ããŒãž2ã®ææ¡ãªã®ã§ããŸã ãã°ããæéããããã§ãããã TC39ã«ã¯ãå°ãªããšãåããããããã«èŠããŸãã
ãã®ã³ã¡ã³ãã«ãããšãæ©ããã°11æã«ã¹ããŒãž3ã«ææ¡ãããå¯èœæ§ãããããã§ãã
ãã³ã¬ãŒã¿ã«ãã£ãŠé¢æ°ã®ã·ã°ããã£ãå€æŽããåé¿ç
空ã®ã¯ãããŒé¢æ°ãè¿œå ããŸã
export default function wapper (cb: any) {
return cb;
}
å®çŸ©ãè¿œå
export function wapper(cb: IterableIterator<0>): Promise<any>;
çµæ
<strong i="13">@some</strong> decorator // run generator and return promise
function *abc() {}
wapper(abc()).then() // valid
/ ping
誰ããããã«å¯Ÿãã解決çãæ¢ããŠãããªããç§ãæãã€ãã1ã€ã®åé¿çã¯ä»¥äžã®ãšããã§ãã
ãã¹ãããããªããžã§ã¯ããå¿ èŠãªãããããã¯æåã®è§£æ±ºçã§ã¯ãããŸãããããã³ã¬ãŒã¿ã®ããããã£ãã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹äžã§ãã©ããã«ããã ãã§ãªãããªããžã§ã¯ãå ã«é 眮ããå¿ èŠããããããããŸãæ©èœããŸãã
ããã¯ãAngular5ã¢ãŒãã«ã«äœ¿çšããŠãããã®ã§ãã
ã«ã¹ã¿ã ConfirmModalComponent
ã§äœ¿çšã§ãã@ModalParams(...)
ãã³ã¬ãŒã¿ããããšä»®å®ããŸãã @ModalParams(...)
ãã³ã¬ãŒã¿ã®ããããã£ãã«ã¹ã¿ã ã³ã³ããŒãã³ãå
ã«è¡šç€ºããã«ã¯ããã³ã¬ãŒã¿ãå€ãå²ãåœãŠãããããã£ãæã€åºæ¬ã¯ã©ã¹ãæ¡åŒµããå¿
èŠããããŸãã
äŸãã°ïŒ
export class Modal {
params: any;
constructor(values: Object = {}) {
Object.assign(this, values);
}
}
export function ModalParams (params?: any) {
return (target: any): void => {
Object.assign(target.prototype, {
params: params
});
};
}
@Component({...})
@ModalOptions({...})
@ModalParams({
width: <number> 300,
title: <string> 'Confirm',
message: <string> 'Are you sure?',
confirmButtonText: <string> 'Yes',
cancelButtonText: <string> 'No',
onConfirm: <(modal: ConfirmModalComponent) => void> (() => {}),
onCancel: <(modal: ConfirmModalComponent) => void> (() => {})
})
export class ConfirmModalComponent extends Modal {
constructor() {
super();
}
confirm() {
this.params.onConfirm(this); // This does not show a syntax error
}
cancel() {
this.params.onCancel(this); // This does not show a syntax error
}
}
ç¹°ãè¿ãã«ãªããŸãããããŸããããã§ã¯ãããŸããããç§ã®ãŠãŒã¹ã±ãŒã¹ã§ã¯ããŸãæ©èœããã®ã§ãä»ã®èª°ããããã圹ç«ã€ãããããªããšæããŸããã
@lansanaã§ãããã¿ã€ããããããŸãããïŒ
@confrariaæ®å¿µãªããããã§ã¯ãããŸããããæ¡åŒµãããžã§ããªãã¯Modal
ã¯ã©ã¹ãå®è£
ãããšããããå®çŸããæ¹æ³ããããããããŸããã ããšãã°ã次ã®ãããªãã®ãæ©èœããå¯èœæ§ããããŸãïŒãã¹ããããŠããŸããïŒã
export class Modal<T> {
params: T;
}
export function ModalParams (params?: any) {
return (target: any): void => {
Object.assign(target.prototype, {
params: params
});
};
}
// The object in @ModalParams() should be of type MyType
@ModalParams({...})
export class ConfirmModalComponent extends Modal<MyType> {
constructor() {
super();
}
}
ïŒ/ãããããããã¿ã€ãã¯ãã³ã¬ãŒã¿ããåãé¢ãããŠããã確ãã«ãããã®2ã€ã䜿çšããããšã¯ã§ããŸãã.. :(ã¯ã©ã¹ãã¡ãœãããå®è£ ããªãå Žåã¯ãšã©ãŒãçºçããŸã.. :(ç§ã¯ããã«ãªããšæããŸãçŸæç¹ã§ãã®ãã¿ãŒã³ã§ã¿ã€ããæ£ããããæ¹æ³ã§ã
ããããããå¯èœã§ããã°ãTypeScriptãã¯ããã«åªããè¡šçŸåã®ãããã®ã«ããããšãã§ããã°çŽ æŽããããšæããŸãã ããŸãããã°ãããã«äœããèµ·ããã§ãããã
@lansanaãããèŠç¹ã¯ãã¯ã©ã¹ãã³ã¬ãŒã¿ããã¯ã©ã¹ã«ä»ã®äœããæ¡åŒµãŸãã¯å®è£ ããå¿ èŠãªãã«ãã¯ã©ã¹ã®ã·ã°ããã£ãèªåã§å€æŽã§ãããšäŸ¿å©ã ãšããããšã§ãïŒããã¯ãäœæ¥ãšã¿ã€ãæ å ±ã®éè€ã§ããããïŒ ã
è£è¶³ïŒããã§ã®äŸã§ã¯ã params
ã¯ãªããžã§ã¯ãåç
§ã§ãããããè£
食ãããã¢ãŒãã«ã³ã³ããŒãã³ãã¯ã©ã¹ã®ãã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹ã§éçã§ããããšã«æ³šæããŠãã ããã å€åããã¯ä»æ§ã«ãããã®ã§ããã ïŒ-ïŒããããç§ã¯éžè±ããŸãã
ç·šéïŒããã«ã€ããŠèãããšããã³ã¬ãŒã¿ãã¯ã©ã¹ã®çœ²åãå€æŽã§ããããã«ããããšã®çæãããããŸãã ã¯ã©ã¹ã®å®è£ ãç¹å®ã®åã¢ãããŒã·ã§ã³ãæ確ã«åããŠãããããã³ã¬ãŒã¿ãæ¥éäžããŠãã®ãã¹ãŠãå€æŽã§ããå Žåãããã¯éçºè ã«ãšã£ãŠã¯ã¡ãã£ãšããããªãã¯ã«ãªããŸãã å€ãã®ãŠãŒã¹ã±ãŒã¹ã¯æããã«æ°ããã¯ã©ã¹ããžãã¯ã®çµã¿èŸŒã¿ã«é¢ä¿ããŠãããããæ®å¿µãªããããããã®å€ãã¯æ¡åŒµãŸãã¯ã€ã³ã¿ãŒãã§ã€ã¹ã®å®è£ ã«ãã£ãŠãã容æã«ãªããŸããããã¯æ¢åã®ã¯ã©ã¹ã·ã°ããã£ãšãé£æºããè¡çªãçºçããå Žåã«é©åãªãšã©ãŒãçºçãããŸãã Angularã®ãããªãã¬ãŒã ã¯ãŒã¯ã¯ãã¡ããããã³ã¬ãŒã¿ãå€çšããŠã¯ã©ã¹ãæ¡åŒµããŸãããèšèšã§ã¯ãã¯ã©ã¹ããã³ã¬ãŒã¿ããæ°ããããžãã¯ããååŸããŸãã¯æ··åããŠãç¬èªã®å®è£ ã§äœ¿çšã§ããããã«ããããšã¯ã§ããŸããããã¬ãŒã ã¯ãŒã¯èª¿æŽããžãã¯ããã®ã¯ã©ã¹ããžãã¯ã ãšã«ãããããã¯ç§ã®_è¬èãª_æèŠã§ãã ïŒ-ïŒ
ãã³ã¬ãŒã¿ãšããã¯ã§ã¯ãªããé«éã¯ã©ã¹ã䜿çšããæ¹ãããããã§ãã 人ã ããã®ãããªãã®ã«ãã³ã¬ãŒã¿ã䜿çšããããšæã£ãŠããããšã¯ç¥ã£ãŠããŸãããcompose + HOCã䜿çšããã®ãéã§ããããããããã®ãŸãŸã«ãªãã§ããã...æ°žé ã«;ïŒMSãªã©ã«ãããšããã³ã¬ãŒã¿ã¯ã¡ã¿ããŒã¿ãã¯ã©ã¹ã«æ·»ä»ããããã®ãã®ã§ãã Angularãªã©ã®ãã³ã¬ãŒã¿ã®å€§èŠæš¡ãªãŠãŒã¶ãŒã確èªããŠãã ããããããã¯ãã®å®¹éã§ã®ã¿äœ¿çšãããŠããããšãããããŸãã ããã§ãªããã°ãTypeScriptã¡ã³ããã説åŸã§ãããšã¯æããŸããã
çã®æ©èœæ§æãå¯èœã«ãããã®ãããªãšã³ã²ãŒãžã¡ã³ããçæãããã®ãããªåŒ·åãªæ©èœããTSããŒã ã«ãã£ãŠé·ãéç¡èŠãããŠããããšã¯ãæ²ããããšã§ãããå°ãå¥åŠã§ãã
ããã¯æ¬åœã«ãã³ãŒãã®èšè¿°æ¹æ³ã«é©åœãããããå¯èœæ§ã®ããæ©èœã§ãã 誰ããBitlyãNPMã®ãããªãã®ã§å°ããªããã¯ã¹ã€ã³ããªãªãŒã¹ããTypescriptã§æ¬åœã«çŽ æŽãããã³ãŒããåå©çšã§ããããã«ããŸãã ç§èªèº«ã®ãããžã§ã¯ãã§ã¯ãããã«@Poolable @Initable @Translatingãäœæãããããããã£ãšå€ãã®ãããžã§ã¯ããäœæããŸãã
ãã¹ãŠã®åŒ·åãªTSã³ã¢ããŒã ããé¡ãããŸãã å®è£ ããããã«ãå¿ èŠãªã®ã¯ããè¿ãããã€ã³ã¿ãŒãã§ãŒã¹ãå°éããããšã ãã§ãã
// taken from my own lib out of context
export function Initable<T extends { new(...args: any[]): {} }>(constructor: T): T & Constructor<IInitable<T>> {
return class extends constructor implements IInitable<T> {
public init(obj: Partial<T> | any, mapping?: any) {
setProperties(this, obj, mapping);
return this
}
}
}
ããã«ããããã®ã³ãŒããæå¥ãªãã«å®è¡ã§ããŸãã
<strong i="14">@Initable</strong>
class Person {
public name: string = "";
public age: number = 0;
public superPower: string | null = null;
}
let sam = new Person();
sam.init({age: 17, name: "Sam", superPower: "badassery"});
@AllNamesRTaken
ç§ã¯ããªãã®æèŠã«åæããŸãããããªãã¯ãã®ããã«åãããšãéæããããšãã§ããŸãïŒ
class Animal {
constructor(values: Object = {}) {
Object.assign(this, values);
}
}
ãããŠãããªãã¯inité¢æ°ããå¿ èŠãšããªãã§ããããããªãã¯ãã ãããããããšãã§ããŸãïŒ
const animal = new Animal({name: 'Fred', age: 1});
@lansana
ãããã§ãããã¯ç§ã®ã³ã³ã¹ãã©ã¯ã¿ãŒãæ±ããŠããŸããŸãã
ãŸãããªããžã§ã¯ããããŒã«å¯èœã«ããããã®åæ§ã®ããã¯ã¹ã€ã³ããã®ä»ã®ãã®ããããŸãã æ§æãéããŠæ©èœãè¿œå ããå¯èœæ§ã ããå¿ èŠã§ãã initã®äŸã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒãæ±æããã«è¡ã£ãããšãå®è¡ããããã®å¿ èŠãªæ¹æ³ã§ãããä»ã®ãã¬ãŒã ã¯ãŒã¯ã§åœ¹ç«ã¡ãŸãã
@AllNamesRTakené·ãéãã®ç¶æ ã«ãããææ¡ã¯ãã§ã«ã¹ããŒãž2ã«ãããããçŸæç¹ã§ãã³ã¬ãŒã¿ã«è§Šããæå³ã¯ãããŸããã https://github.com/tc39/proposal-decoratorsãå®æããã®ãåŸ ã£ãŠãã ãããããããã°ã誰ããåæãã圢åŒã§ããããååŸã§ããå¯èœæ§ãé«ããªããŸãã
@Kukkimonsuta
ç§ãèŠæ±ããŠããã®ã¯çŽç²ã«ã¿ã€ãã«é¢ãããã®ã§ãããæ©èœã«é¢ãããã®ã§ã¯ãªããããç§ã¯ããªãã«åŒ·ãå察ããŸãã ãããã£ãŠãESã®ãã®ãšã¯ã»ãšãã©é¢ä¿ããããŸããã äžèšã®ç§ã®è§£æ±ºçã¯ãã§ã«æ©èœããŠããŸããç§ã¯ãã ãã£ã¹ãããå¿
èŠã¯ãããŸãã
@AllNamesRTakenããã¯ãèŠåãªãã§ããã¯ã¹ã€ã³ã䜿çšããŠ_ä»æ¥_è¡ãããšãã§ããŸãã
function setProperties(t: any, o: any, mapping: any) {}
type Constructor<T> = { new(...args: any[]): T };
interface IInitable<T> {
init(obj: Partial<T> | any, mapping?: any): this;
}
// taken from my own lib out of context
function Initable<T extends Constructor<{}>>(constructor: T): T & Constructor<IInitable<T>> {
return class extends constructor implements IInitable<T> {
public init(obj: Partial<T> | any, mapping?: any) {
setProperties(this, obj, mapping);
return this
}
}
}
class Person extends Initable(Object) {
public name: string = "";
public age: number = 0;
public superPower: string | null = null;
}
let sam = new Person();
sam.init({age: 17, name: "Sam", superPower: "badassery"});
å°æ¥ãããã¯ã¹ã€ã³ã®ææ¡ãJSã«åã蟌ããšã次ã®ããšãå¯èœã«ãªããŸãã
mixin Initable {
public init(obj: Partial<T> | any, mapping?: any) {
setProperties(this, obj, mapping);
return this
}
}
class Person extends Object with Initable {
public name: string = "";
public age: number = 0;
public superPower: string | null = null;
}
let sam = new Person();
sam.init({age: 17, name: "Sam", superPower: "badassery"});
@justinfagnaniããã¯ã¹ã€ã³ã¯ç§ããããã®æ©èœãå§ããæ¹æ³ã§ãããç§ã®å®è£ ãå®éã«ã¯ããªãã説æããããã«æ©èœããŸãïŒ
class Person extends Initable(Object) {
public name: string = "";
public age: number = 0;
public superPower: string | null = null;
}
let sam = new Person();
sam.init({age: 17, name: "Sam", superPower: "badassery"});
ããã¯åé¿çãšããŠã¯ãããã§ããããã³ã¬ãŒã¿ãã¿ã€ããå€æŽã§ããããã«ããããšã®ã¡ãªãããå®éã«åãé€ãããã§ã¯ãããŸããã
ç·šéïŒãŸããinitã®ããŒã·ã£ã«ã®ã¿ã€ãã³ã°ã倱ããŸãã
ãã®æ©èœã䜿çšãããšãHoCãããç°¡åã«äœæã§ããããã«ãªããŸã
ãã®æ©èœãè¿œå ãããããšãé¡ã£ãŠããŸã
@kgtkrãããç§ããããã²ã©ã欲ããã£ãŠããäž»ãªçç±ã§ã...
react-router
ã®å®çŸ©ã«ãå°ãç·æ¥äºæ
ããããŸããããã¯ãã¯ã©ã¹è£
食ã€ã³ã¿ãŒãã§ã€ã¹ãããåã®å®å
šæ§ã®æ¹ãéèŠã§ãããšå€æãã人ãããããã§ãã äžçªã®çç±ã¯ã withRouter
ãããã€ãã®å°éå
·ããªãã·ã§ã³ã«ããããšã§ãã
ä»ã人ã
ãè£
食ã®ä»£ããã«withRouter
ã®é¢æ°ã€ã³ã¿ãŒãã§ãŒã¹ã䜿çšããããšãäœåãªããããŠãã確å·ãããããã§ãã
ãã®æ©èœã解決ãå§ãããšãäžçã¯ãã幞ããªå Žæã«ãªããŸãã
åã確å·*ã¯ã material-uiã¿ã€ãã³ã°ãšwithStyle
ã§çºçããŸãããããã¯ããã³ã¬ãŒã¿ãšããŠäœ¿çšããããã«èšèšãããŠããŸãããã¿ã€ãã»ãŒããªæ¹æ³ã§äœ¿çšããã«ã¯ãTypeScriptãŠãŒã¶ãŒã䜿çšããå¿
èŠããããŸããéåžžã®é¢æ°ãšããŠã ã»ããã¯ã»ãšãã©èœã¡çããŸããããããã¯ãããžã§ã¯ãã®æ°èŠåå
¥è
ã«ãšã£ãŠç¶ç¶çãªæ··ä¹±ã®åå ã§ãïŒ
*ãŸããã確å·ãã¯åŒ·ãèšèãããããŸãã
ç§ã¯ãããé·ãéèŠãŠããŸãããããããå°çãããŸã§ãä»ã®äººãç§ã®å°ããªããã¯ããå©çãåŸãŠãäžäœäºææ§ã®ããæ¹æ³ã§ãã®åäœãå®çŸã§ããããšãé¡ã£ãŠããŸãã ããããè¶
åºæ¬çãªScalaã¹ã¿ã€ã«ã®ã±ãŒã¹ã¯ã©ã¹copy
ã¡ãœãããå®è£
ããããšã§ã...
ç§ã¯ãã³ã¬ãŒã¿ã次ã®ããã«å®è£ ããŠããŸãïŒ
type Constructor<T> = { new(...args: any[]): T };
interface CaseClass {
copy(overrides?: Partial<this>): this
}
function CaseClass<T extends Constructor<{}>>(constructor: T): T & Constructor<CaseClass> {
return class extends constructor implements CaseClass {
public copy(overrides: Partial<this> = {}): this {
return Object.assign(Object.create(Object.getPrototypeOf(this)), this, overrides);
}
}
}
ãã®ã³ãŒãã¯ã copy
ã¡ãœãããã¢ã¿ãããããå¿åã¯ã©ã¹ãäœæããŸãã ãã³ã¬ãŒã¿ããµããŒãããç°å¢ã§ã¯ãJavaScriptã§æåŸ
ã©ããã«æ©èœããŸãã
ãããTypeScriptã§äœ¿çšããå®éã«åã·ã¹ãã ã«ã¿ãŒã²ããã¯ã©ã¹ã®æ°ããã¡ãœãããåæ ãããã«ã¯ã次ã®ããã¯ã䜿çšã§ããŸãã
class MyCaseClass extends CaseClass(class {
constructor(
public fooKey: string,
public barKey: string,
public bazKey: string
) {}
}) {}
MyCaseClass
ã®ãã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹ã¯ã CaseClass
ãã³ã¬ãŒã¿å
ã®å¿åã¯ã©ã¹ããç¶æ¿ãããcopy
ã¡ãœããã®åãå
¬éããŸãã ãŸããTypeScriptã宣èšãããåã®å€æŽããµããŒãããŠããå Žåããã®ã³ãŒãã¯ãäºæããªãããªãããªãã«ãéåžžã®ãã³ã¬ãŒã¿ãŒæ§æ<strong i="18">@CaseClass</strong> etc
ã«ç°¡åã«å€æŽã§ããŸãã
ããã次ã®ã¡ãžã£ãŒTypeScriptãªãªãŒã¹ã§èŠãããã®ã¯çŽ æŽãããããšã§ãããããã·ã¯ã©ã¹ã®å¥åŠãªæ··ä¹±ããšã¯ã¹ããŒããã代ããã«ãããã¯ãªãŒã³ã§ç°¡æœãªã³ãŒãã«åœ¹ç«ã€ãšæããŸãã
ãã®æ©èœã¯ãã€å©çšå¯èœã«ãªããŸããïŒ
ã¯ã©ã¹ãã³ã¬ãŒã¿ã䜿çšããŠãç¹°ãè¿ãããã¿ã¹ã¯ãåŠçãããã£ãã®ã§ãã
ããããã¯ã©ã¹ãåæåãããšã次ã®ãšã©ãŒãçºçããŸãïŒ Expected 0 arguments, but got 1
function Component<T extends { new(...args: any[]): {} }>(target: T) {
return class extends target {
public constructor(...args: any[]) {
super(...args);
resolveDependencies(this, args[0])
}
}
}
<strong i="8">@Component</strong>
export class ExampleService {
@Inject(ExampleDao) private exampleDao: ExampleDao;
// <strong i="9">@Component</strong> will automatically do this for me
// public constructor(deps: any) {
// resolveDependencies(this, deps);
// }
public getExample(id: number): Promise<Example | undefined> {
return this.exampleDao.getOne(id);
}
}
new ExampleService({ exampleDao }) // TS2554: Expected 0 arguments, but got 1.
ãã®æ©èœãããã«å©çšã§ããããã«ãªãããšãé¡ã£ãŠããŸãïŒ :)
@ iainreid820ãã®ã¢ãããŒãã䜿çšããŠãå¥åŠãªãã°ãçµéšããŸãããïŒ
é·ãéãåŸ
ã¡ãã ããïŒ ãããŸã§ã®éãããã¯çŸåšã®ããŒããããäžã®äœãã«ãã£ãŠè§£æ±ºãããŠããŸããïŒ
åé¡5453ãªã©ïŒ
ç§ã¯MaterialUIã䜿çšããŠããŸãããTypeScriptãwithStyles
ã®ãã³ã¬ãŒã¿æ§æããµããŒãããŠããªãããšãèªèããªããã°ãªããŸããã§ããïŒ https ïŒ//material-ui.com/guides/typescript/#decorating -components
次ã®TypeScriptãªãªãŒã¹ã§ãã®å¶éãä¿®æ£ããŠãã ããã ã¯ã©ã¹ãã³ã¬ãŒã¿ã¯ãä»ã®ãšããç§ã«ã¯ããªã圹ã«ç«ããªãããã§ãã
Morphism Jsã®ã¡ã³ãããšããŠãããã¯ãã®çš®ã®ã©ã€ãã©ãªã®å€§ããªå¶éã§ãã é¢æ°ãã³ã¬ãŒã¿ã®å©çšè
ãé¢æ°ã®ã¿ãŒã²ããã¿ã€ããæå®ããå¿
èŠããªãããã«ããããšæããŸãhttps://github.com/nobrainr/morphism#--toclassobject-decoratorããã§ãªããã°ãHOFã®ä»£ããã«ãã³ã¬ãŒã¿ã䜿çšãããšå°ã圹ã«ç«ããªãããã«èãããŸãð
ããã«åãçµãèšç»ã¯ãããŸããïŒ ãã®æ©èœãå®çŸããã®ã«åœ¹ç«ã€æ¹æ³ã¯ãããŸããïŒ åãã£ãŠæè¬ããŸãïŒ
@bikeshedderã®MaterialUIã®äŸã¯ãã¯ã©ã¹ããã¯ã¹ã€ã³ã®ãŠãŒã¹ã±ãŒã¹ã§ãããããã¯ã¹ã€ã³ããé©åãªã¿ã€ããååŸã§ããŸãã ãã以å€ã®ïŒ
const DecoratedClass = withStyles(styles)(
class extends React.Component<Props> {
...
}
æžããŸãïŒ
class DecoratedClass extends withStyles(styles)(React.Component<Props>) {
...
}
@justinfagnaniããã¯ç§ã«ã¯ããŸããããŸããïŒ
ãããç§ã®ã³ãŒãã§ãïŒ https ïŒ//gist.github.com/G-Rath/654dff328dbc3ae90d16caa27a4d7262
@ G-Rath代ããã«new () => React.Component<Props, State>
ãæ©èœããã¯ãã ãšæããŸããïŒ
@emyannãµã€ã³ãã¯ãããŸããã æ°ããã³ãŒãã§èŠç¹ãæŽæ°ããŸããããããã¯ããªããæå³ããããšã§ããïŒ
class CardSection extends withStyles(styles)(new () => React.Component<Props, State>) {
ã©ã®ããã«ãã©ãŒãããããŠããåºæ¬çã«extends withStyles(styles)(...)
ã¯é©åãªææ¡ã®ããã«ã¯èãããŸããã withStylesã¯ã¯ã©ã¹ããã¯ã¹ã€ã³ã§ã¯ãããŸããã
withStylesã¯ã³ã³ããŒãã³ãã¯ã©ã¹A
ãåãåããã¯ã©ã¹B
ãäœæããŸããããã¯ãã¬ã³ããªã³ã°æã«ã¯ã©ã¹A
ãã¬ã³ããªã³ã°ããããã«å°éå
·+ classes
å°éå
·ãæž¡ããŸãã
withStylesã®æ»ãå€ãæ¡åŒµãããšãå®éã«classes
ãããããåãåãA
ã¯ã©ã¹ãå®è£
ãã代ããã«ã B
ã©ãããŒãæ¡åŒµããããšã«ãªããŸãã
ã©ã®ããã«ãã©ãŒãããããŠããextends withStylesïŒstylesïŒïŒ...ïŒã¯åºæ¬çã«é©åãªææ¡ã®ããã«ã¯èãããŸããã withStylesã¯ã¯ã©ã¹ããã¯ã¹ã€ã³ã§ã¯ãããŸããã
ããã¯ããã ãªãããã«å€ãã®åçºãããã®ãââããããŸããã
ãšã¯èšããã®ã®ããã³ã¬ãŒã¿ã¯ã¹ããŒãž3ã«éåžžã«è¿ããšèããŠããã®ã§ãTSã¯ãŸããªãããã§é©åãªãµããŒããåããããã«ãªããšæããŸãã
ããããããã¯ãªãŒã³ãªæ§æãæãã§ãã人ã ã®è©±ãèããŸãã ãã³ã¬ãŒã¿ãšããŠè€æ°ã®HoCãé©çšããå Žåã 䜿çšããäžæçãªåé¿çã¯ãå®éã«è€æ°ã®ãã³ã¬ãŒã¿ããã€ãé¢æ°å ã«ã©ãããããã®çŽç²é¢æ°ã䜿çšããŠã³ã³ããŒãã³ããè£ é£Ÿããããšã§ãã äŸãã°
@flow([
withStyles(styles),
connect(mapStateToProps),
decorateEverything(),
])
export class HelloWorld extends Component<Props, State> {
...
}
ããã§ã flow
ã¯lodash.flow
ã§ãã å€ãã®utilã©ã€ãã©ãªã¯ã recompose
ã Rx.pipe
ãªã©ã®ãããªãã®ãæäŸããŸãããã©ã€ãã©ãªãã€ã³ã¹ããŒã«ããããªãå Žåã¯ããã¡ãããç¬èªã®åçŽãªãã€ãé¢æ°ãäœæã§ããŸãã
ããã¯ããã³ã¬ãŒã¿ã䜿çšããªããããèªã¿ããããšæããŸãã
export const decoratedHelloWorld = withStyles(styles)(
connect(mapStateToProps)(
decorateEverything(
HelloWorld
))))
ç§ãããã䜿çšãããã1ã€ã®çç±ã¯ããã³ã¬ãŒã¿ã®ä»æ§ãçºè¡šãããŠé©åã«ãµããŒãããããšããã®ãã¿ãŒã³ãç°¡åã«èŠã€ããŠçœ®ãæããããgrepãããã§ããããšã§ãã
@justinfagnaniå¥åŠãªããšã«ã extends React.Component<Props, State>
ãextends withStyles(styles)(React.Component<Props, State>)
ã«å€æŽããããšãããšãESLintããæ§æãšã©ãŒãçºçããããã@ G-Rathã®åãšã©ãŒãåãæ¹æ³ã§ç¢ºèªã§ããŸããã§ããã
ãããã次ã®ãããªããšããããšã new
ã®åé¡ïŒããããåãåé¡ïŒïŒã衚瀺ãããããšã«æ°ã¥ããŸããã
class MyComponent extends React.Component<Props, State> {
/* ... */
}
const _MyComponent = withStyles(styles)(MyComponent)
const test = new _MyComponent // <--------- ERROR
ãšã©ãŒã¯æ¬¡ã®ãšããã§ãã
Cannot use 'new' with an expression whose type lacks a call or construct signature.
ããã¯ãMaterial UIã«ãã£ãŠè¿ãããåãã³ã³ã¹ãã©ã¯ã¿ãŒã§ã¯ãªãããšãæå³ããŸããïŒããããã¹ãã§ããïŒïŒ
@ sagar-smãããããããªã¢ã«UIã¿ã€ãã«ãã£ãŠæ¡åŒµãããæ£ããã¿ã€ããååŸããŸããïŒ ããªããããããããã«ã¯æãããŸããã
åèãŸã§ã«ãMaterial UIã®withStyles
ããã³ã¬ãŒã¿ãšããŠäœ¿çšããããšããŠãæ©èœããªãã£ããããããã«ééããŸããããã®è³ªåãããŸããïŒ https ïŒ//stackoverflow.com/questions/53138167
ãããå¿ èŠãªå Žåã¯ãéåæé¢æ°ãbluebirdãšããŠè¿ãããšãã§ããŸã
ç§ã¯äŒŒããããªããšãããããšããŸããã ATMç§ã¯æ¬¡ã®åé¿çã䜿çšããŠããŸãïŒ
ãŸãããããç§ã®ãmixinããã³ã¬ãŒã¿ã§ã
export type Ctor<T = {}> = new(...args: any[]) => T
function mixinDecoratorFactory<MixinInterface>() {
return function(toBeMixed: MixinInterface) {
return function<MixinBase extends Ctor>(MixinBase: MixinBase) {
Object.assign(MixinBase.prototype, toBeMixed)
return class extends MixinBase {} as MixinBase & Ctor<MixinInterface>
}
}
}
ã€ã³ã¿ãŒãã§ã€ã¹ãããã³ã¬ãŒã¿ãäœæãã
export interface ComponentInterface = {
selector: string,
html: string
}
export const Component = mixinDecoratorFactory<ComponentInterface>();
ãããŠãããç§ãããã䜿ãæ¹æ³ã§ãïŒ
@Component({
html: "<div> Some Text </div>",
selector: "app-test"
})
export class Test extends HTMLElement {
test = "test test"
constructor() {
super()
console.log("inner; test:", this.test)
console.log("inner; html:", this.html)
console.log("inner; selector:", this.selector)
}
}
export interface Test extends HTMLElement, ComponentInterface {}
window.customElements.define(Test.prototype.selector, Test)
const test = new Test();
console.log("outer; test:", test.test)
console.log("outer; html:", test.html)
console.log("outer; selector:", test.selector)
ããªãã¯ã¯ãããŒãžããã宣èšãäœæããããã«ãã¯ã©ã¹ãšåãååã®ã€ã³ã¿ãŒãã§ãŒã¹ãäœæããããšã§ãã
ããã§ããã¯ã©ã¹ã¯ã¿ã€ãTest
ãšããŠã®ã¿è¡šç€ºãããŸãããtypescriptããã®ãã§ãã¯ã¯æ©èœããŠããŸãã
@
ãªãã§ãã³ã¬ãŒã¿ã䜿çšããå Žå-è¡šèšæ³ã¯åã«é¢æ°ãšããŠåŒã³åºãã ãã§ãæ£ãã亀差åãååŸããŸã-ã¿ã€ãã¯äœ¿çšã§ããŸããããã¯ã©ã¹èªäœã®å
éšã§ã¿ã€ããã§ãã¯ããæ©èœã¯å€±ãããŸããã€ã³ã¿ãŒãã§ã€ã¹ã®ããªãã¯ã¯ãããããèŠãç®ã¯ãã£ãšéãã§ãã äŸãã°ïŒ
let Test2Comp = Component({
html: "<div> Some Text 2 </div>",
selector: "app-test2"
}) (
class Test2 extends HTMLElement {
test = "test test"
constructor() {
super()
console.log("inner; test:", this.test)
console.log("inner; html:", this.html) // no
console.log("inner; selector:", this.selector) // no
}
})
interface Test2 extends HTMLElement, ComponentInterface {} //no
window.customElements.define(Test2Comp.prototype.selector, Test2Comp)
const test2 = new Test2Comp();
console.log("outer; test:", test2.test)
console.log("outer; html:", test2.html)
console.log("outer; selector:", test2.selector)
ãããã®ã¢ãããŒãã«ã€ããŠã©ãæããŸããïŒ ããã¯çŸããã¯ãããŸããããåé¿çãšããŠã¯æ©èœããŸãã
ãã®åé¡ã«ã€ããŠäœãé²å±ã¯ãããŸããïŒ ããã¯éåžžã«åŒ·åãªæ©èœã®ããã§ãããŸããŸãªå¯èœæ§ã解ãæŸã¡ãŸãã ãã³ã¬ãŒã¿ã¯ãŸã å®éšçã§ããããããã®åé¡ã¯çŸåšã»ãšãã©å€ããªã£ãŠãããšæããŸããïŒ
ãã®@ andy-ms @ ahejlsberg @ sandersnã«é¢ããå ¬åŒå£°æãããã°æ¬åœã«çŽ æŽãããã§ãããã ð
ãã³ã¬ãŒã¿ãå®æãããŸã§ãããã§ã¯äœãããªãå¯èœæ§ããããŸãã
@ DanielRosenwasser-ããã§ãfinalizedããšã¯ã©ãããæå³ã§ããïŒ TC39ã®ã¹ããŒãž3ã¯é©æ Œã§ããïŒ
ç§ã¯åœŒãããããŸã§å°éããããšã«æ°ã¥ããŠããŸããã§ããïŒ åœŒãã¯ãã€ã¹ããŒãž3ã«å°éããŸãããïŒ ããã¯æè¿ã§ããïŒ
圌ãã¯ãŸã ããŠããŸããã 1æã®TC39ããŒãã£ã³ã°ã§ã圌ãã¯åã³ã¹ããŒãž2ããã¹ããŒãž3ã«é²ãæºåãã§ããŠãããšæããŸãã
詳现ã«ã€ããŠã¯ãè°é¡ãç£èŠããããšãã§ããŸãã
æ£è§£ã§ãïŒ1æã«æé²ãããã©ããã¯ç¢ºèªã§ããŸãããïŒã ç§ã¯åœŒããããã«çãããšãã«ã¹ããŒãž3ãè³æ ŒãåŸããã©ããã ããå°ããŠããŸããã
ç§ã®æèŠã§ã¯ããã³ã¬ãŒã¿ã®ææ¡ã«ã¯ãŸã å€ãã®æ·±å»ãªåé¡ãããããã1æã«ã¹ããŒãž3ã«é²ããšãåé¡ã®ããã¯ã©ã¹ãã£ãŒã«ãã®ææ¡ãglobalThisã®ææ¡ãšåãããã«åã³ééããç¯ããŸãã
@hax詳ããæããŠããã ããŸããïŒ
ç§ã¯æ¬åœã«ãããæãã§ããŠãæ²ããããšã«åé¡ã«ã€ããŠã®ã³ãã¥ãã±ãŒã·ã§ã³ã®æ¬ åŠãèŠã€ããæ®å¿µãªããåé¡ã«ã€ããŠèããããšããããŸããã
@AllNamesRTakenãã³ã¬ãŒã¿ææ¡ã®åé¡ãªã¹ãã確èªããŠãã ããã ðããšãã°ããã³ã¬ãŒã¿åŒæ°ã®ååŸã®export
ã¯ãã¹ããŒãž3ã®ãããã«ãŒã§ãã
ãŸããAPIã®åèšèšãªã©ãææ¡ãããå€æŽãããã€ããããŸããããã¯ãææ¡ãã¹ããŒãž3ã§å®å®ããŠããªãããšãæå³ãããšæããŸãã
ãŸããåé¡ã®ããã¯ã©ã¹ãã£ãŒã«ãã®ææ¡ã«ãé¢é£ããŠããŸãã ã¯ã©ã¹ãã£ãŒã«ãã¯ã¹ããŒãž3ã«å°éããŠããŸãããåé¡ãå€ãããŸãã ç§ãæžå¿µããŠãã倧ããªåé¡ã¯ããã³ã¬ãŒã¿ïŒããšãã°ãä¿è·ãããŠããïŒã«å€ãã®åé¡ãæ®ããŠããããšã§ããããã¯ãäž¡æ¹ã®ææ¡ã«ãšã£ãŠæªãããšã§ãã
ç§ã¯TC39ã®ä»£è¡šè ã§ã¯ãªãããšã«æ³šæããŠãã ããããŸããäžéšã®TC39ã®ä»£è¡šè ã¯ãå€ãã®åé¡ã®çŸåšã®ç¶æ³ã«ã€ããŠã®ç§ã®ã³ã¡ã³ãã«åæããŸããã ïŒç¹ã«ãçŸåšã®TC39ããã»ã¹ã§ã¯ãå€ãã®ç©è°ãéžãåé¡ã§å€§ããªå€±æããããšåŒ·ãæããŸããäžéšã®åé¡ããã³ã¬ãŒã¿ã«å»¶æããŠããå®éã«ã¯åé¡ã解決ãããŸããããã³ã¬ãŒã¿ã®ææ¡ãããè匱ã«ããã ãã§ããïŒ
ãããã¯ç解ãããææ¡ã¯ããŸããããšæããŸãããããã§ã¯ææ¡ã®ç¶æ ã«ã€ããŠã¯è°è«ããªãã£ãã»ãããããšæããŸãã
ååãªèªä¿¡ãæã£ãã¹ããŒãž3ãŸãã¯ã¹ããŒãž4ã¯ãããããæ°ããææ¡ãå®è£ ããå Žæã ãšæããŸããããããã°ããã®åé¡ãæ€èšããããšãã§ããŸãã
ãããšã«ããããšãïŒ ã¹ããŒãž3ã¯éåžžã4ã«å¯Ÿãã匷ãèªä¿¡ãæå³ããããã1æã®äŒè°ã§ã¯æã亀差ããŸããã
ãããŠãããã§ãã³ã¬ãŒã¿ã®è°è«ãå§ããŠãããŠããããšãã ãã®æ©èœãåŒãèµ·ãããæããšèªè»¢è»ã®è±èœã®ã¬ãã«ã¯å¥åŠã§ãã ç§ã¯ãã®ãããªãã®ãèŠãããšããããŸããð
èšé²ã®ããã«ãåãããšã«ã€ããŠã®æ©èœèŠæ±ããããŸããïŒ https ïŒ//github.com/Microsoft/TypeScript/issues/8545
åä»ãªããšã«ãJavaScriptããã³ã³ãã€ã«ããå ŽåãTypeScriptã¯ãã®æ©èœãããçšåºŠãµããŒãããŸãïŒhttps://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#better-handling-for-namespace-patterns-in -js-filesïŒïŒ
// javascript via typescript
var obj = {};
obj.value = 1;
console.log(obj.value);
TypeScriptã³ãŒãèªäœã«ã€ããŠããé¢æ°ã«é¢ããŠã®ã¿ïŒïŒïŒïŒhttps://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#properties-declarations-on-functionsïŒïŒ
function readImage(path: string, callback: (err: any, image: Image) => void) {
// ...
}
readImage.sync = (path: string) => {
const contents = fs.readFileSync(path);
return decodeImageSync(contents);
}
@DanielRosenwasser @arackafã¹ããŒãž3ã«ç§»è¡ããææ¡ã«ã€ããŠäœãèšãããããšã¯ãããŸããïŒ ãã³ã¬ãŒã¿ã䜿çšãããšãã«ããããã¿ã€ãé¢æ°ãã¯ã©ã¹ã«è¿œå ããã©ã€ãã©ãªãæ§ç¯ããããšããŠããŸãã
圌ãã¯ææ°ã®TC39äŒè°ã§åé²ããŸããã§ããã 圌ãã¯æ¬¡ã®äŒè°ã§åã³åé²ãããããããŸããã ãã ããããã¯äžæã§ãã ãã®æç¹ã§ãææ¡ã«ã€ããŠã¯å€ãã®ããšãæµ®ã圫ãã«ãªã£ãŠããŸãã
ããã«èå³ã®ãã人ã¯ãææ¡èªäœã远跡ããããšããå§ãããŸããããã«ãããã¹ã¬ãããç£èŠããŠãã人ãTSã¡ã³ããã®éšé³ãæããããšãã§ããŸãã
ããã«é¢ããæŽæ°ã¯ãããŸããïŒ
åé¿çïŒè§åºŠïŒïŒïŒ https://stackblitz.com/edit/iw-ts-extends-with-fakes?file=src%2Fapp%2Fextends-with-fakes.ts
import { Type } from '@angular/core';
export function ExtendsWithFakes<F1>(): Type<F1>;
export function ExtendsWithFakes<F1, F2>(): Type<F1 & F2>;
export function ExtendsWithFakes<F1, F2, F3>(): Type<F1 & F2 & F3>;
export function ExtendsWithFakes<F1, F2, F3, F4>(): Type<F1 & F2 & F3 & F4>;
export function ExtendsWithFakes<F1, F2, F3, F4, F5>(): Type<F1 & F2 & F3 & F4 & F5>;
export function ExtendsWithFakes<RealT, F1>(realTypeForExtend?: Type<RealT>): Type<RealT & F1>;
export function ExtendsWithFakes<RealT, F1, F2>(realTypeForExtend?: Type<RealT>): Type<RealT & F1 & F2>;
export function ExtendsWithFakes<RealT, F1, F2, F3>(realTypeForExtend?: Type<RealT>): Type<RealT & F1 & F2 & F3>;
export function ExtendsWithFakes<RealT, F1, F2, F3, F4>(
realTypeForExtend?: Type<RealT>
): Type<RealT & F1 & F2 & F3 & F4>;
export function ExtendsWithFakes<RealT, F1, F2, F3, F4, F5>(
realTypeForExtend?: Type<RealT>
): Type<RealT & F1 & F2 & F3 & F4 & F5> {
if (realTypeForExtend) {
return realTypeForExtend as Type<any>;
} else {
return class {} as Type<any>;
}
}
interface IFake {
fake(): string;
}
function UseFake() {
return (target: Type<any>) => {
target.prototype.fake = () => 'hello fake';
};
}
class A {
a() {}
}
class B {
b() {}
}
@UseFake()
class C extends ExtendsWithFakes<A, IFake, B>(A) {
c() {
this.fake();
this.a();
this.b(); // failed at runtime
}
}
ãã®ããã®éãç°¡åãªè§£æ±ºçã«ã€ããŠã©ãæããŸããïŒ
https://stackoverflow.com/a/55520697/1053872
Mobx-state-treeã¯ã cast()
é¢æ°ã§åæ§ã®ã¢ãããŒãã䜿çšããŸãã æ°åã¯è¯ããªããã©âŠããŸãæ°ã«ãªããŸããã äœãè¯ããã®ãåºãŠããããã€ã§ãç°¡åã«åãåºããŸãã
ãã®â€ïžã«æ²¿ã£ãŠäœãã§ããããã«ãªãããã§ã
ããã¯ãã³ã¬ãŒã¿ãæã€ã¹ãåã§ã¯ãããŸãããïŒ
class B<C = any> {}
function ChangeType<T>(to : T) : (from : any) => T;
function InsertType<T>(from : T) : B<T>;
@ChangeType(B)
class A {}
// A === B
// or
<strong i="7">@InsertType</strong>
class G {}
// G === B<G>
const g = new G(); // g : B<G>
A === B // equals true
const a : B = new A(); // valid
const b = new B();
typeof a === typeof b // valid
è£ é£Ÿãããã¯ã©ã¹ããããã£ãå ¥åããããã®åé¿çãäœæããã®ã«ããªãã®æéãè²»ãããŸããã ãã®ã¹ã¬ããã®ã·ããªãªã«å¯Ÿããå®è¡å¯èœãªè§£æ±ºçã«ãªããšã¯æããŸãããããã®äžéšã圹ç«ã€å ŽåããããŸãã èå³ãããã°ãMediumã®ç§ã®æçš¿ããã§ãã¯ããŠãã ããã
ãã®åé¡ã«é¢ããæŽæ°ã¯ãããŸããïŒ
ãããã©ããã£ãŠãã£ãŠãã®ïŒ
ãã®åé¡ã®çµæãçŸåšã©ã®ããã«æ©èœããŠããŸããïŒ
ããã¯ã¹ã€ã³ã¯ã©ã¹ã䜿çšããŠãã®å¹æãåŸãããšãã§ããŸã
https://mariusschulz.com/blog/mixin-classes-in-typescript
@Bnayaã¯ãç§ãã¡ãä»æãã§ãããã®ã§ã¯ãããŸãã;ïŒã
ãã³ã¬ãŒã¿ã䜿çšãããšãå€ãåŠæ ¡ã®Javaã®ããã«äœ¿çšããäºå®ã®ãªãã¯ã©ã¹ãäœæããªãããã«ããããšãã§ããŸãã ãã³ã¬ãŒã¿ã䜿çšãããšãã¯ã©ã¹ãåŒãç¶ãã³ã¢æ©èœãå®è¡ããããã«äžè¬åãããæ©èœãæ§æã§ãããéåžžã«ã¯ãªãŒã³ã§æŽç¶ãšããæ§æã¢ãŒããã¯ãã£ãå¯èœã«ãªããŸãã ãããããã¯ã¹ã€ã³ã¯ãããè¡ãããšãã§ããŸãããããã¯ãã³ããšã€ãã§ãã
ãã³ã¬ãŒã¿ã®ææ¡ã¯éå»æ°ãæã§å€§å¹ ã«å€æŽãããŸãããTSããŒã ããããã«äºææ§ããªããªãçŸåšã®å®è£ ã«ãã€ã§ãæè³ããå¯èœæ§ã¯ã»ãšãã©ãããŸããâ¢ã
次ã®ãªãœãŒã¹ãã芧ã«ãªãããšããå§ãããŸãã
ãã³ã¬ãŒã¿ã®ææ¡ïŒ https ïŒ//github.com/tc39/proposal-decorators
TypeScriptããŒããããïŒ https ïŒ//github.com/microsoft/TypeScript/wiki/Roadmap
@Bnayaã¯ãç§ãã¡ãä»æãã§ãããã®ã§ã¯ãããŸãã;ïŒã
ãã³ã¬ãŒã¿ã䜿çšãããšãå€ãåŠæ ¡ã®Javaã®ããã«äœ¿çšããäºå®ã®ãªãã¯ã©ã¹ãäœæããªãããã«ããããšãã§ããŸãã ãã³ã¬ãŒã¿ã䜿çšãããšãã¯ã©ã¹ãåŒãç¶ãã³ã¢æ©èœãå®è¡ããããã«äžè¬åãããæ©èœãæ§æã§ãããéåžžã«ã¯ãªãŒã³ã§æŽç¶ãšããæ§æã¢ãŒããã¯ãã£ãå¯èœã«ãªããŸãã ãããããã¯ã¹ã€ã³ã¯ãããè¡ãããšãã§ããŸãããããã¯ãã³ããšã€ãã§ãã
ãã®æ··åã§ã¯ãªããã¯ã©ã¹ã
ããã¯æªãã³ããŒã®ãã®ã§ã¯ãããŸãã
ãã€ãã©ã€ã³æŒç®åãå°çãããšãæ§æãåççã«ãªããŸã
ããã¯ã¹ã€ã³ã¯ã©ã¹ã䜿çšããŠãã®å¹æãåŸãããšãã§ããŸã
ã¯ã©ã¹ãã¡ã¯ããªã®ããã¯ã¹ã€ã³ã¯ãTypeScriptã§ã¯èŠçã«ãªãå¯èœæ§ããããŸãã ããã§ãªãå Žåã§ããã¯ã©ã¹ãé¢æ°ã§ã©ããããŠããã¯ã¹ã€ã³ã«å€æããå¿ èŠããããããéåžžã«å®åçã§ãããµãŒãããŒãã£ã®ã¯ã©ã¹ãã€ã³ããŒãããå Žåã¯ããããç°¡åã«å®è¡ã§ããªãå ŽåããããŸãã
以äžã¯ãã¯ããã«åªããŠãããåçŽã§ãã¯ãªãŒã³ã§ãããã€ã³ããŒãããããµãŒãããŒãã£ã¯ã©ã¹ã§æ©èœããŸãã ã¬ã¬ã·ãŒã¹ã¿ã€ã«ã®ãã³ã¬ãŒã¿ããã©ã³ã¹ãã€ã«ãã以å€ã®ãã©ã³ã¹ãã€ã«ãªãã§ãã¬ãŒã³JavaScriptã§æ£åžžã«åäœããŠããŸããã class
esã¯å®å
šã«ãã€ãã£ããªclass
esã®ãŸãŸã§ãã
class One {
one = 1
foo() { console.log('foo', this.one) }
}
class Two {
two = 2
bar() { console.log('bar', this.two) }
}
class Three extends Two {
three = 3
baz() { console.log('baz', this.three, this.two) }
}
@with(Three, One)
class FooBar {
yeah() { console.log('yeah', this.one, this.two, this.three) }
}
let f = new FooBar()
console.log(f.one, f.two, f.three)
console.log(' ---- call methods:')
f.foo()
f.bar()
f.baz()
f.yeah()
ãããŠChromeã®åºåã¯æ¬¡ã®ãšããã§ãã
1 2 3
---- call methods:
foo 1
bar 2
baz 3 2
yeah 1 2 3
ããã«ããããã¹ãŠã®å®åæããªããŠããã¯ã©ã¹ãã¡ã¯ããªã®ããã¯ã¹ã€ã³ãè¡ãããšãå®å šã«å®çŸã§ããŸãã ã¯ã©ã¹ã®é¢æ°ã©ãããŒã¯äžèŠã«ãªããŸããã
ãã ãããåç¥ã®ããã«ããã³ã¬ãŒã¿ã¯å®çŸ©ãããã¯ã©ã¹ã®ã¿ã€ããå€æŽã§ããŸããã ð¢
ãããã£ãŠãåœé¢ã¯æ¬¡ã®ããšãã§ããŸãããå¯äžã®æ³šæç¹ã¯ãä¿è·ãããã¡ã³ããŒã¯ç¶æ¿ã§ããªããšããããšã§ãã
// `multiple` is similar to `@with`, same implementation, but not a decorator:
class FooBar extends multiple(Three, One) {
yeah() { console.log('yeah', this.one, this.two, this.three) }
}
ä¿è·ãããã¡ã³ããŒã倱ãããåé¡ã¯ã multiple
å®è£
ã®æ¬¡ã®2ã€ã®äŸã§ç€ºãããŠããŸãïŒã¿ã€ãã«é¢ããéããå®è¡æã®å®è£
ã¯ç°¡æœã«ããããã«çç¥ãããŠããŸãïŒã
Two.prototype.two
ãç¶æ¿ã§ããŸãããä¿è·ãããã¡ã³ããŒãå«ãã¿ã€ãããããããæ¹æ³ãæ¬åœã«æ¬²ããã§ãã
ã¯ã©ã¹ãé¢æ°ãšããŠåŒã³åºãããšãã§ãããã³ã¬ãŒã¿ãããã®ã§ãããã¯ç§ã«ãšã£ãŠéåžžã«äŸ¿å©ã§ãã
ããã¯æ©èœããŸãïŒ
export const MyClass = withFnConstructor(class MyClass {});
ããã¯æ©èœããŸããïŒ
<strong i="10">@withFnConstructor</strong>
export class MyClass {}
ãã®æ©èœãåºãŠãããšãã«ã¯ãªãŒã³ã¢ããããã®ã¯ããã»ã©é£ããããšã§ã¯ãªãåé¿çã¯ã宣èšã®ããŒãžãšã«ã¹ã¿ã ã¿ã€ãå®çŸ©ãã¡ã€ã«ã䜿çšããŠå®è¡ã§ããŸãã
ãã§ã«ãããæã£ãŠããïŒ
// ClassModifier.ts
export interface Mod {
// ...
}
// The decorator
export function ClassModifier<Args extends any[], T>(target: new(...args: Args) => T): new(...args: Args) => T & Mod {
// ...
}
// MyClass.ts
<strong i="9">@ClassModifier</strong>
export MyClass {
// ...
}
次ã®ãã¡ã€ã«ãè¿œå ããŸãïŒæ©èœãå ¬éããããåé€ããããã¡ã€ã«ïŒïŒ
// MyClass.d.ts
import { MyClass } from './MyClass';
import { Mod } from './ClassModifier';
declare module './MyClass' {
export interface MyClass extends Mod {}
}
å¥ã®å¯èœãªåé¿ç
declare class Extras { x: number };
this.Extras = Object;
class X extends Extras {
constructor() {
super();
// a modification to object properties that ts will not pick up
Object.defineProperty(this, 'x', {value: 3});
}
}
const a = new X()
a.x // 3
2015幎ã«éå§ããããŸã ä¿çäžã§ãã ããã«å€ãã®é¢é£ããåé¡ãããããã®https://medium.com/p/caf24aabcb59/responses/showã®ãããªèšäºã§ãããåé¿çã瀺ããããšããŠããŸãïŒããã¯å°ãããããŒã§ããã圹ã«ç«ã¡ãŸãïŒ
誰ããããã«å ãåœãŠãããšã¯å¯èœã§ããïŒ ããã¯ãŸã å éšã®è°è«ã®ããã«èæ ®ãããŠããŸããïŒ
tl; dr-ãã®æ©èœã¯TC39ã§åŠšå®³ãããŠããŸãã ããã«ã€ããŠTSã®äººã ã責ããããšã¯ã§ããŸããã æšæºã«ãªããŸã§å®è£ ããŸããã
ããããããã¯ãã€ã¯ããœããã§ãã圌ãã¯ãããå®è£ ããŠãæšæºã®äººã ã«èšãããšãã§ããŸã-ã人ã ã¯ãã§ã«ç§ãã¡ã®ããŒãžã§ã³ã䜿çšããŠããŸããïŒtrollfaceïŒ
ããã§ã®åé¡ã¯ãTypeScriptããã³ã¬ãŒã¿ãå®è£ ããŠããããã³ã¬ãŒã¿ã®ææ¡ã_å€§å¹ ã«_ïŒåŸæ¹äºææ§ã®ãªãæ¹æ³ã§ïŒå€æŽãããããšã§ãã äžéšã®äººã ã¯TypeScriptã®çŸåšã®ãã³ã¬ãŒã¿ã®åäœãšã»ãã³ãã£ã¯ã¹ã«äŸåããŠãããããããã¯æ°ãããã³ã¬ãŒã¿ãå®æããŠå®è£ ããããšãã«èŠçãªç¶æ³ã«ã€ãªããã§ãããã TypeScriptããŒã ã¯ããã®åé¡ã®ã¢ã¯ã·ã§ã³ãé¿ããããšåŒ·ãæã£ãŠããŸãããããããšãçŸåšã®éæšæºã®ãã³ã¬ãŒã¿ã®äœ¿çšãããã«ä¿é²ãããæçµçã«ã¯æ°ãããã³ã¬ãŒã¿ã®å®è£ ãžã®ç§»è¡ãããã«å°é£ã«ãªãããã§ãã åºæ¬çã«ãç§ã¯å人çã«ãããèµ·ãã£ãŠããã®ãèŠãŠããŸããã
ã¡ãªã¿ã«ãç§ã¯æè¿ïŒ36348ãäœæããŸãããããã¯ãããªã確å®ãªåé¿çãæäŸããæ©èœã®ææ¡ã§ãã æ°è»œã«èŠãŠ/ãã£ãŒãããã¯ãäžããŠ/éè®ã«ããŠãã ããã ð
tl; dr-ãã®æ©èœã¯TC39ã§åŠšå®³ãããŠããŸãã ããã«ã€ããŠTSã®äººã ã責ããããšã¯ã§ããŸããã æšæºã«ãªããŸã§å®è£ ããŸããã
ãã®äºå®ãèãããšãéçºããŒã ãç°¡åãªèª¬æãšã¹ããŒã¿ã¹ã®æŽæ°ãäœæããTC39ããããå¿ èŠãªæ®µéã«é²ãããŸã§ãã®å€æãããã¯ããã®ãè³¢æãããããŸããã
ãããèªãã§ãã人ã¯ãåé¡ã«äœãéã¿ããããŸããïŒ
å®éãã»ãšãã©ãã¹ãŠã®ãã³ã¬ãŒã¿é¢é£ã®äŒè©±ãå®ã«æµ®ããŠããŸãã äŸïŒ https ïŒ//github.com/Microsoft/TypeScript/issues/2607
ãã³ã¬ãŒã¿ã®å°æ¥ã«ã€ããŠããçšåºŠæ確ã«ããããšã¯ãè²¢ç®è ã«å¿ èŠãªæ©èœãå®è£ ããããã«äŸé Œããããšã«ã€ããŠã§ãã£ãŠãã圹ç«ã€ã§ãããã æ確ãªã¬ã€ãã³ã¹ããªããã°ããã³ã¬ãŒã¿ã®æªæ¥ã¯ãŒãããŠããŸã
TypeScriptããŒã ãããªãã·ã§ã³ã®é£éãå®çŸããã®ã«åœ¹ç«ã£ãã®ãšåãããã«ããã³ã¬ãŒã¿ã®ææ¡ã«å¯ŸããŠç©æ¥µçãªåœ¹å²ãæããããšãã§ããã°ãšæããŸãã ç§ãå©ããããšæã£ãŠããŸããããŸã èšèªéçºã«æºãã£ãŠããªããããæåã®æ¹æ³ãããããŸããïŒ-/
ããŒã å šäœãããã³ãããžã§ã¯ããšããŠã®TypeScriptã«ã€ããŠè©±ãããšã¯ã§ããŸãããããã³ã¬ãŒã¿ã®å®è£ ãTypeScriptã®å®è£ ãããã§ã«åå²ããŠããããšãèãããšãããã解決ããŠç¢ºèªããããŸã§ãæ°ãããã³ã¬ãŒã¿ã®äœæ¥ãè¡ãå¯èœæ§ã¯äœããšæããŸãã
ãã®ææ¡ã¯ãŸã 掻çºã«éçºãããŠãããä»é±TC39ã§åãäžããããŸããhttps://github.com/tc39/proposal-decorators/issues/305
ãã®å Žåã®@ortaã¯ãã¯ã©ã¹ãã³ã¬ãŒã¿ã«é¢ããããã¥ã¡ã³ããæŽæ°ããå¿ èŠããããšæããŸãã ããã¯ãããè¿°ã¹ãŠããŸã
ã¯ã©ã¹ãã³ã¬ãŒã¿ãå€ãè¿ãå Žåãã¯ã©ã¹å®£èšã¯æäŸãããã³ã³ã¹ãã©ã¯ã¿é¢æ°ã«çœ®ãæããããŸãã
ãŸããããã¥ã¡ã³ãã®æ¬¡ã®äŸã¯ã Greeter
ã€ã³ã¹ã¿ã³ã¹ã¿ã€ããããããã£newProperty
ãæã€ããšã瀺åããŠããããã§ãããããã¯æ£ãããããŸããã
function classDecorator<T extends {new(...args:any[]):{}}>(constructor:T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
}
}
<strong i="13">@classDecorator</strong>
class Greeter {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}
console.log(new Greeter("world"));
è¿ãããã¯ã©ã¹ã®ã€ã³ã¿ãŒãã§ãŒã¹ãå ã®ã¯ã©ã¹ã眮ãæããªãããšãããã¥ã¡ã³ãã«è¿œå ãã䟡å€ããããšæããŸãã
èå³æ·±ãããšã«ãç§ã¯TypeScriptã®å€ãããŒãžã§ã³ããããããã¹ãããŸãããããã®ã³ãŒããµã³ãã«ãæ©èœããæ©äŒãèŠã€ããããšãã§ããŸããã§ããïŒ 3.3.3ã®äŸïŒ-ããã§ããç§ã¯åæããŸãã
ç§ã¯https://github.com/microsoft/TypeScript-Website/issues/443ãäœæããŸãã-誰ãããã®classDecoratorã«æ瀺çãªäº€å·®åãæãããæ¹æ³ãç¥ã£ãŠããå Žåã¯ããã®åé¡ã«ã³ã¡ã³ãããŠãã ãã
äžèšã®ããã¥ã¡ã³ãã®åé¡ãç§ãæ··ä¹±ãããã®ã§ãç§ã¯ããã«è¡ãçããŸããã ãã³ã¬ãŒã¿ããã®æ»ãå€ã®å眲åãTSã³ã³ãã€ã©ã«ãã£ãŠèªèãããã°çŽ æŽãããã®ã§ããããã®å€§ããªå€æŽã®ä»£ããã«ãããã¥ã¡ã³ããæ確ã«ããå¿ èŠãããããšã«åæããŸãã
èšé²ã®ããã«ãããã¯ç§ã@ortaã®PRããã®é¢é£ããã¥ã¡ã³ãã®åœ¢åŒã§è©Šã¿ãŠãããã®ã®åçŽåãããããŒãžã§ã³ã§ãïŒ
interface HasNewProperty {
newProperty: string;
}
function classDecorator<T extends { new (...args: any[]): {} }>(
constructor: T
) {
return class extends constructor implements HasNewProperty {
newProperty = "new property";
hello = "override";
};
}
<strong i="8">@classDecorator</strong>
class Greeter {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}
console.log(new Greeter("world"));
// Alas, this line makes the compiler angry because it doesn't know
// that Greeter now implements HasNewProperty
console.log(new Greeter("world").newProperty);
æãåèã«ãªãã³ã¡ã³ã
åãããšãã¡ãœããã«ã圹ç«ã¡ãŸãã
éåæãã³ã¬ãŒã¿ã¯ãæ»ãå€ã®ã¿ã€ãã
Promise<any>
ã«å€æŽããããšã«ãªã£ãŠããŸãã