Slide 1

Slide 1 text

susisu 2026-05-22 TSKaigi 2026 Stage 3 Decorators Ͱ Ͱ͖Δ͜ͱ / Ͱ͖ͳ͍͜ͱ

Slide 2

Slide 2 text

‣ id:susisu / @susisu / @susisu2413 ‣ גࣜձࣾ͸ͯͳ
 Web ΞϓϦέʔγϣϯΤϯδχΞ / γχΞ ΤϯδχΞ ͜Μʹͪ͸

Slide 3

Slide 3 text

࠷ۙྑ͔ͬͨ͜ͱ

Slide 4

Slide 4 text

࠷ۙྑ͔ͬͨ͜ͱ

Slide 5

Slide 5 text

"Stage 3 Decorators"

Slide 6

Slide 6 text

Stage 3 Decorators ‣ TypeScript Ͱ͸ඪ४ԽҎલͷσίϨʔλ͕࣮ݧతʹ࣮૷͞Ε࢖ΘΕ͖ͯͨ ‣ --experimentalDecorators, --emitDecoratorMetadata, re fl ect-metadata

Slide 7

Slide 7 text

Stage 3 Decorators ‣ TypeScript Ͱ͸ඪ४ԽҎલͷσίϨʔλ͕࣮ݧతʹ࣮૷͞Ε࢖ΘΕ͖ͯͨ ‣ --experimentalDecorators, --emitDecoratorMetadata, re fl ect-metadata ‣ TC39 Ͱඪ४Խ͕ਐΊΒΕɺத৺తͳ࢓༷͕ Stage 3 ʹͳͬͨ ‣ Decorators, Decorator Metadata

Slide 8

Slide 8 text

Stage 3 Decorators ‣ TypeScript Ͱ͸ඪ४ԽҎલͷσίϨʔλ͕࣮ݧతʹ࣮૷͞Ε࢖ΘΕ͖ͯͨ ‣ --experimentalDecorators, --emitDecoratorMetadata, re fl ect-metadata ‣ TC39 Ͱඪ४Խ͕ਐΊΒΕɺத৺తͳ࢓༷͕ Stage 3 ʹͳͬͨ ‣ Decorators, Decorator Metadata ‣ TypeScript ʹ΋ 5.0 / 5.2 Ͱ Stage 3 ͷ࢓༷͕࣮૷͞Εͨ

Slide 9

Slide 9 text

Stage 3 Decorators ‣ TypeScript Ͱ͸ඪ४ԽҎલͷσίϨʔλ͕࣮ݧతʹ࣮૷͞Ε࢖ΘΕ͖ͯͨ ‣ --experimentalDecorators, --emitDecoratorMetadata, re fl ect-metadata ‣ TC39 Ͱඪ४Խ͕ਐΊΒΕɺத৺తͳ࢓༷͕ Stage 3 ʹͳͬͨ (2022 ʙ 2023) ‣ Decorators, Decorator Metadata ‣ TypeScript ʹ΋ 5.0 / 5.2 Ͱ Stage 3 ͷ࢓༷͕࣮૷͞Εͨ (2023) ‣ͦΕ͔Β໿ 3 ೥͕ܦա

Slide 10

Slide 10 text

Stage 3 Decorators ʹ·ͭΘΔٙ໰ ‣ ͦ΋ͦ΋σίϨʔλͬͯԿʁ

Slide 11

Slide 11 text

Stage 3 Decorators ʹ·ͭΘΔٙ໰ ‣ ͦ΋ͦ΋σίϨʔλͬͯԿʁ ‣ --experimentalDecorators ͔ΒͲ͏มΘͬͨͷʁ

Slide 12

Slide 12 text

Stage 3 Decorators ʹ·ͭΘΔٙ໰ ‣ ͦ΋ͦ΋σίϨʔλͬͯԿʁ ‣ --experimentalDecorators ͔ΒͲ͏มΘͬͨͷʁ ‣ ࢓༷΍ΤίγεςϜ͸ࠓͲ͏͍͏ঢ়گʁ

Slide 13

Slide 13 text

Stage 3 Decorators ʹ·ͭΘΔٙ໰ ‣ ͦ΋ͦ΋σίϨʔλͬͯԿʁ ‣ --experimentalDecorators ͔ΒͲ͏มΘͬͨͷʁ ‣ ࢓༷΍ΤίγεςϜ͸ࠓͲ͏͍͏ঢ়گʁ ‣ ͿͬͪΌ͚໾ʹཱͭͷʁ

Slide 14

Slide 14 text

Q1. ͦ΋ͦ΋σίϨʔλͬͯԿʁ

Slide 15

Slide 15 text

ͦ΋ͦ΋σίϨʔλͬͯԿʁ ‣ class ͷػೳΛ֦ு / ϝλσʔλΛ෇༩͢ΔͨΊͷػೳ ‣ ͪΐ͏Ͳؔ਺ʹର͢Δߴ֊ؔ਺ͷΑ͏ͳ໾ׂ @decorate class MyClass { @decorate accessor myField: number = 0; @decorate myMethod(): void { /* ... */ } } ͍ͭ͜Β

Slide 16

Slide 16 text

ྫ: ϩά / τϨʔε ‣ ڭՊॻతͳϢʔεέʔε ‣ ϝιουΛϥοϓͯ͠ϩά / τϨʔε৘ใΛه࿥͢Δ class MyClass { @log myMethod(): void { /* ... */ } } const myInstance = new MyClass(); myInstance.myMethod(); // → myMethod called

Slide 17

Slide 17 text

ྫ: ϩά / τϨʔε ‣ ڭՊॻతͳϢʔεέʔε ‣ ϝιουΛϥοϓͯ͠ϩά / τϨʔε৘ใΛه࿥͢Δ function log( target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext Return>, ): ((this: This, ...args: Args) => Return) | void { return function (this, ...args) { console.log(`${String(context.name)} called`); return target.call(this, ...args); }; } ؔ਺Λड͚औͬͯ ؔ਺Λฦ͢

Slide 18

Slide 18 text

ྫ: DI ‣ InversifyJS, TSyringe, TypeDI, NestJS ͳͲ ‣ ϑΟʔϧυ΍Ҿ਺ʹ஋Λ஫ೖ͢ΔͨΊͷϝλσʔλΛ෇༩͢Δ // --experimentalDecorators, --emitDecoratorMetadata @injectable() class MyApp { constructor(@inject("Clock") clock: Clock) { /* ... */ } } // ... const myApp = container.get("MyApp");

Slide 19

Slide 19 text

ྫ: ORM / (de)serialization ‣ TypeORM, class-transformer ͳͲ ‣ ֤ϑΟʔϧυΛΤϯίʔυ / σίʔυ͢ΔͨΊͷϝλσʔλΛ෇༩͢Δ // --experimentalDecorators, --emitDecoratorMetadata @Entity() export class User { @PrimaryGeneratedColumn("uuid") id!: string; @Column() name!: string; @CreateDateColumn() createdAt!: Date; }

Slide 20

Slide 20 text

ྫ: ϧʔςΟϯάఆٛ ‣ NestJS ͳͲ ‣ HTTP ϦΫΤετͱϝιουΛ݁ͼ͚ͭΔϝλσʔλΛ෇༩͢Δ // --experimentalDecorators, --emitDecoratorMetadata @Controller("users") export class UsersController { @Get() findAll(@Req() request: Request): string { /* ... */ } }

Slide 21

Slide 21 text

ྫ: Observable ‣ MobX ͳͲ ‣ ΫϥεͷϑΟʔϧυ͕มԽͨ࣌͠ʹ௨஌͢Δ class Checkbox { @observable accessor checked = false; @action toggle(): void { this.checked = !this.checked; } }

Slide 22

Slide 22 text

Q2. --experimentalDecorators ͔Β Ͳ͏มΘͬͨͷʁ

Slide 23

Slide 23 text

--experimentalDecorators ͱ஥ؒͨͪ ‣ --experimentalDecorators ‣ ࣮ݧతͳσίϨʔλΛ༗ޮԽ ‣ re fl ect-metadata ‣ ࣮ݧతͳσίϨʔλͱ૊Έ߹ΘͤͯϝλσʔλΛѻ͏ύοέʔδ ‣ --emitDecoratorMetadata ‣ re fl ect-metadata Λ࢖ͬͯίϯύΠϧ࣌ͷܕ৘ใΛϝλσʔλͱͯ͠෇༩

Slide 24

Slide 24 text

Stage 3 Decorators ͷ࢓༷ ‣ Decorators ‣ ֓Ͷ --experimentalDecorators ʹରԠ ‣ σίϨʔλຊମ ‣ Decorator Metadata ‣ ֓Ͷ re fl ect-metadata ʹରԠ ‣ σίϨʔλΛ࢖ͬͯΫϥεʹϝλσʔλΛ෇༩ ‣ (--emitDecoratorMetadata ͸ʁ)

Slide 25

Slide 25 text

ओͳมԽ఺ ‣ ྑ͍ͱ͜Ζ ‣ Class fi elds (public / private / static) ͷαϙʔτ ‣ Auto-accessors ͷ௥Ճ ‣ ඪ४ػೳ͚ͩͰϝλσʔλΛ෇༩Ͱ͖ΔΑ͏ʹͳͬͨ ‣ ྑ͘ͳ͍ͱ͜Ζʁ ‣ ࣗ༝౓͕௿Լͨ͠ ‣ Ҿ਺σίϨʔλ͕ະαϙʔτ ‣ --emitDecoratorMetadata ͕ඇରԠ

Slide 26

Slide 26 text

Class fi elds ͷαϙʔτ ‣ ES2022 Ͱ class fi elds (public / private / static) ͕௥Ճ͞Εͨ ‣ TypeScript ͷ public / private म০ࢠ͡Όͳ͍ํͰ͢ class MyClass { foo: number = 1; #bar: number = 2; static baz: number = 3; static #qux: number = 4; }

Slide 27

Slide 27 text

Class fi elds ͷαϙʔτ ‣ --experimentalDecorators Ͱ͸ class fi elds ʹର͢Δαϙʔτ͕ऑ͔ͬͨ ‣ private ͸׬શඇରԠɺstatic Λ۠ผͰ͖ͳ͍ɺॳظԽϩδοΫʹ৮Εͳ͍ // --experimentalDecorators function fieldDecorator( target: Target, key: string | symbol ): void { // ... } private fi eld ͸ key Ͱ͸ࢀরͰ͖ͳ͍ ϝλσʔλΛ෇༩͢Δ͘Β͍͔͠Ͱ͖ͳ͍

Slide 28

Slide 28 text

Class fi elds ͷαϙʔτ ‣ Stage 3 Decorators Ͱ͸ class fi elds Λαϙʔτ ‣ private ΍ static Λ໰୊ͳ͘ѻ͑ΔɺॳظԽϩδοΫʹ৮ΕΔɺ function fieldDecorator( target: undefined, context: ClassFieldDecoratorContext, ): ((this: This, initialValue: Value) => Value) | void { // ... } ໭Γ஋Λฦ͢ͱॳظԽϩδοΫΛΧελϚΠζͰ͖Δ context ͷϝιου / ϑϥάͰ
 private fi elds ΋ѻ͑Δ͠
 private / static ͷ۠ผ΋Ͱ͖Δ

Slide 29

Slide 29 text

Auto-accessors ͷ௥Ճ ‣ --experimentalDecorators Ͱ͸ϑΟʔϧυͷಡΈॻ͖Λѻ͏ͷ͕൥ࡶͩͬͨ ‣ ࣗ໌ͳ getter / setter Λॻ͘ඞཁ͕͋Δ // --experimentalDecorators class MyClass { private _field: number = 0; @log get field(): number { return this._field; } set field(value: number) { this._field = value; } } fi elds ʹର͢ΔσίϨʔλͰ͸
 ಡΈॻ͖Λѻ͑ͳ͍ͷͰ
 setter / getter Λ࢖͏

Slide 30

Slide 30 text

Auto-accessors ͷ௥Ճ ‣ Auto-accessor ͷ௥ՃʹΑͬͯɺ͜ͷύλʔϯͷهड़͕؆୯ʹͳͬͨ ‣ private fi eld ͱͦͷ getter / setter Λੜ੒ͯ͘͠ΕΔΑ͏ͳΠϝʔδ class MyClass { @log accessor field: number = 0; } Auto-accessor ʹର͢ΔσίϨʔλͰ͸
 ಡΈॻ͖Λѻ͑Δ

Slide 31

Slide 31 text

ඪ४ػೳͰϝλσʔλΛ෇༩ ‣ --experimentalDecorators ࣗମʹ͸ϝλσʔλΛ෇༩͢Δ࢓૊Έ͕ͳ͍ ‣ ୅ΘΓʹ re fl ect-metadata ύοέʔδΛཔΔ͜ͱʹͳ͍ͬͯͨ // --experimentalDecorators import "reflect-metadata"; function fieldDecorator( target: Target, key: string | symbol ): void { Reflect.defineMetadata("foo", 42, target, key); }

Slide 32

Slide 32 text

ඪ४ػೳͰϝλσʔλΛ෇༩ ‣ Decorator Metadata Ͱ͸ context / Symbol.metadata Λ࢖ͬͯ
 ϝλσʔλΛಡΈॻ͖Ͱ͖ΔΑ͏ʹͳͬͨ function fieldDecorator( target: undefined, context: ClassFieldDecoratorContext, ): void { context.metadata["foo"] = 42; }

Slide 33

Slide 33 text

ࣗ༝౓ͷ௿Լ ‣ --experimentalDecorators ͸͔ͳΓࣗ༝౓͕ߴ͔ͬͨ ‣ prototype ΍ property descriptor Λ৮ͬͯ class ͷܗΛมߋͰ͖Δ // --experimentalDecorators function methodDecorator( target: Target, key: string | symbol, descriptor: TypedPropertyDescriptor<(this: Target, ...args: Args) => Return>, ): TypedPropertyDescriptor<(this: Target, ...args: Args) => Return> | void { // ... } prototype

Slide 34

Slide 34 text

ࣗ༝౓ͷ௿Լ ‣ Stage 3 Decorators Ͱ͸جຊతʹ͸௚઀ͷର৅͔͠৮Εͳ͘ͳͬͨ ‣ ୅ΘΓʹΫϥεͷܗ͕੩తʹܾ·ΓɺΤϯδϯͷ࠷దԽʹ༏͘͠ͳͬͨ function methodDecorator( target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext Return>, ): ((this: This, ...args: Args) => Return) | void { // ... } ௚઀ͷର৅

Slide 35

Slide 35 text

Ҿ਺σίϨʔλͷະαϙʔτ ‣ --experimentalDecorators ʹ͋ͬͨҾ਺σίϨʔλ͸ະαϙʔτ ‣ Ҿ਺ʹରͯ͠ݸผʹϝλσʔλΛ෇༩Ͱ͖ͳ͍ // --experimentalDecorators @injectable() class MyApp { constructor(@inject("Clock") clock: Clock) { /* ... */ } } ͜Ε

Slide 36

Slide 36 text

Ҿ਺σίϨʔλͷະαϙʔτ ‣ ຊ࣭తʹ͸ඞཁͰ͸ͳ͍͸ͣ ‣ ಉ͡ϝλσʔλ͸ class ࣗମ΍ϝιου΁ͷσίϨʔλͰ΋෇༩Ͱ͖Δ @injectable() @inject(["Clock"]) class MyApp { constructor(clock: Clock) { /* ... */ } }

Slide 37

Slide 37 text

--emitDecoratorMetadata ඇରԠ ‣ ίϯύΠϧ࣌ͷܕ৘ใΛϝλσʔλͱͯ͠෇༩͢Δػೳ ‣ DI ΍ ORM ͳͲͰ࢖ΘΕ͖ͯͨ ‣ ݩʑ TypeScript ݻ༗ͷػೳͰɺඪ४Խ͸શ͘͞Ε͍ͯͳ͍ ‣ Stage 3 Decorators / Decorator Metadata ΁ͷରԠ΋ߦΘΕ͍ͯͳ͍ ‣ ݱࡏͰ͸ TypeScript ࣗମ͕ඇඪ४΍ܕΛݩʹͨ͠ίʔυੜ੒Λࢤ޲͍ͯ͠ ͳ͍ ‣ ݩʑޓ׵ੑʹ΋೉͕͋Δ

Slide 38

Slide 38 text

มԽ఺·ͱΊ ‣ ྑ͍ͱ͜Ζ ‣ Class fi elds (public / private / static) ͷαϙʔτ ‣ Auto-accessors ͷ௥Ճ ‣ ඪ४ػೳ͚ͩͰϝλσʔλΛ෇༩Ͱ͖ΔΑ͏ʹͳͬͨ ‣ ྑ͘ͳ͍ͱ͸Ұ֓ʹ͸ݴ͑ͳ͍ͱ͜Ζ ‣ ࣗ༝౓͸௿Լ͕ͨ͠ɺTS Ͱ͸ͨͿΜࠔΒͳ͍͠࠷దԽʹ΋༏͍͠ ‣ Ҿ਺σίϨʔλ͸ະαϙʔτ͕ͩɺຊ࣭తʹ͸Ͱ͖Δ͜ͱ͸ݮ͍ͬͯͳ͍ ‣ --emitDecoratorMetadata ͸ඇରԠ͕ͩɺඇޓ׵ͷ೰Έ΋ͳ͘ͳΔ

Slide 39

Slide 39 text

Q3. ࢓༷΍ΤίγεςϜ͸ࠓͲ͏͍͏ঢ়گʁ

Slide 40

Slide 40 text

࢓༷΍ΤίγεςϜ͸ࠓͲ͏͍͏ঢ়گʁ ‣ ҰݴͰݴ͏ͱ: ΍΍ݫ͍͠

Slide 41

Slide 41 text

࢓༷ ‣ Decorators / Decorator Metadata ͸ݱࡏ Stage 3 ‣ ׬ྃ͸ Stage 4 ‣ ݱ࣌఺Ͱ͸ Test262 (ޓ׵ੑςετ) ͕ະ׬੒ ‣ Stage 4 ʹਐΉͨΊʹ͸ Test262 Λ௨ա͢Δޓ׵࣮૷͕ෳ਺ඞཁ ‣ ςετέʔεͱ࢓༷ͷهड़ͷໃ६΋ࢦఠ͞Ε͍ͯͯɺ΋͏গ͔͔͠Γͦ͏

Slide 42

Slide 42 text

࣮૷ ‣ tsc, babel, esbuild, swc ͳͲͷτϥϯεύΠϥ͸ Stage 3 ͷ࢓༷Λ࣮૷ࡁΈ ‣ oxc ͸·ͩ (Test262 ଴ͪ) ‣ V8, SpiderMonkey, JSC ͳͲͷΤϯδϯ͸ະ࣮૷ ‣ ਖ਼֬ʹ͸ V8 ΍ SpiderMonkey Ͱ͸࣮૷͸ਐΜͰ͍ΔΑ͏͕ͩະग़ՙ ‣ धཁ͕ݶఆతͳ͜ͱɺͦ΋ͦ΋ Test262 ͕ະ׬੒ͳ͜ͱͱɺͦΕʹΑͬͯ ग़ՙ͢ΔϦεΫ͕ߴ͍͜ͱͳͲ͕͋Γ༷ࢠݟதͬΆ͍

Slide 43

Slide 43 text

ϥΠϒϥϦ / ϑϨʔϜϫʔΫ ‣ Stage 3 Decorators ΁ͷҠߦΛ׬ྃͨ͠ϥΠϒϥϦ͸ग़͖͍ͯͯΔ ‣ MobX ͳͲ ‣ ҰํͰੲ͔Β͋Δ΋ͷͷଟ͘͸ --experimentalDecorators ͔ΒະҠߦ ‣ InversifyJS, TSyringe, TypeDI, TypeORM, NestJS, etc. ‣ Ҿ਺σίϨʔλͱ --emitDecoratorMetadata ͕ͳ͍͜ͱɺͦΕʹΑͬͯ
 ΠϯλʔϑΣʔε͕มΘͬͯ͠·͏͜ͱ͕ओͳཧ༝ͱͯ͠ڍ͛ΒΕΔ

Slide 44

Slide 44 text

Ҿ਺ʹର͢ΔσίϨʔλ ‣ ࢓༷ࣗମ͸ఏҊதͰɺݱࡏ Stage 1 ‣ ҎԼͷΑ͏ͳҙݟ΋͋Γঢ়گ͸ݫ͍͠ ‣ σίϨʔλͷͨΊ͚ͩʹ class Λ࢖͏ͱ͍͏࿪ΜͩઃܭΛආ͚ΔͨΊɺ
 ؔ਺σίϨʔλ (ಉ͘͡ Stage 1) ͱҰॹʹਐΊΔ΂͖ ‣ ؔ਺σίϨʔλ͸ͦΕ͸ͦΕͰ͙͢ʹ͸࿩͕·ͱ·Γͦ͏ʹͳ͍ ‣ ͦ΋ͦ΋ຊ࣭తʹඞཁͳͷ͔ʁ

Slide 45

Slide 45 text

--emitDecoratorMetadata ‣ ݱࡏͷ TypeScript ͷํ਑ (ܕΛݩʹίʔυੜ੒͠ͳ͍) ʹ൓͢ΔͨΊɺ࣮૷͞ ΕΔՄೳੑ͸ඇৗʹ๡͍͠ ‣ ʮٕज़తʹෆՄೳͰ͸ͳ͍͕ɺ·࣮ͣ૷͠ͳ͍ʯͱ໌ݴ͞Ε͍ͯΔ ‣ tsc Ҏ֎ͷτϥϯεύΠϥ / type stripping ΋޿͘࢖ΘΕΔΑ͏ʹͳ͍ͬͯΔ ͕ɺͦΕΒͰαϙʔτ͞ΕΔݟࠐΈ΋ͳ͍

Slide 46

Slide 46 text

·ͱΊΔͱ ‣ Decorators / Decorator Metadata ͕ Stage 4 ʹਐΉͨΊʹ͸ Test262 Λ͸͡Ί ٞ࿦ͷऩଋͱޓ׵࣮૷͕ඞཁ ‣ τϥϯεύΠϥͷ࣮૷͸ਐΜ͕ͩɺΤϯδϯͷ࣮૷͸·༷ͩࢠݟத ‣ ϥΠϒϥϦ / ϑϨʔϜϫʔΫͷҠߦ͸ɺओʹҾ਺σίϨʔλ΍
 --emitDecoratorMetadata ͕ͳ͍͜ͱΛཧ༝ʹਐΜͰ͍ͳ͍ ‣ Ҿ਺σίϨʔλͷ࢓༷͸ͦ͏؆୯ʹ͸ਐ·ͳͦ͞͏ͩ͠ɺ
 --emitDecoratorMetadata ͸଴͍ͬͯͯ΋དྷͳ͍ ‣ τϥϯεύΠϥ͕͋Ε͹࢖͑Δ͕ɺશମతʹ͸΋͏গ͕࣌ؒ͠ඞཁ͔

Slide 47

Slide 47 text

Q4. ͿͬͪΌ͚໾ʹཱͭͷʁ

Slide 48

Slide 48 text

ͿͬͪΌ͚໾ʹཱͭͷʁ ‣ ͍͔ͭ͘ͷϢʔεέʔεʹ͍ͭͯɺҎԼͷೋͭͷ؍఺ͰݟͯΈ·͠ΐ͏ ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔

Slide 49

Slide 49 text

ྫ: ϩά / τϨʔε ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → Yes (class ࢖༻͕ଥ౰ͳΒ) class MyClass { @log myMethod(): void { /* ... */ } } const myInstance = new MyClass(); myInstance.myMethod(); // → myMethod called

Slide 50

Slide 50 text

ྫ: όϦσʔγϣϯ / ܖ໿ʹΑΔઃܭ ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → Yes (class ࢖༻͕ଥ౰ͳΒ) class Stack { // ... @pre(function (this, _value) { return this.size < this.capacity; }) @post(function (this, _result, value) { return this.size > 0 && this.#items[this.size - 1] === value; }) push(value: T): void { /* ... */ } // ... }

Slide 51

Slide 51 text

ྫ: this ͷ bind ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → Yes (class ࢖༻͕ଥ౰ͳΒ) class MyClass { value: number = 42; method(): void { console.log(this.value); } } const myInstance = new MyClass(); const fn = myInstance.method; fn(); // => ランタイムエラー

Slide 52

Slide 52 text

ྫ: this ͷ bind ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → Yes (class ࢖༻͕ଥ౰ͳΒ) class MyClass { value: number = 42; @bound method(): void { console.log(this.value); } } const myInstance = new MyClass(); const fn = myInstance.method; fn(); // => 42

Slide 53

Slide 53 text

ྫ: DI ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes (࣮૷͸ଘࡏ͢Δ) ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → No @injectable("MyApp") class MyApp { @inject("Clock") clock!: Clock; } // ... const myApp = container.get("MyApp"); Ҿ਺σίϨʔλ͸࢖͑ͳ͍ͷͰ
 ϑΟʔϧυʹ஫ೖ͢ΔͳͲ

Slide 54

Slide 54 text

ྫ: DI ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes? (࣮૷͸ଘࡏ͢Δ) ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → No ‣ ૉ๿ʹίϯετϥΫλ஫ೖͰࡁΉέʔε΋͋Δ ‣ ͦ΋ͦ΋ DI ʹ class ͕ඞਢ͔ͱ͍͏ͱͦ͏Ͱ΋ͳ͍ ‣ ͦ΋ͦ΋ DI ͕ৗʹඞਢ͔ͱ͍͏ͱͦ͏Ͱ΋ͳ͍ (vi.mock() Ͱे෼ͱ͔)

Slide 55

Slide 55 text

ྫ: ORM / (de)serialization ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes (هड़͸૿͑Δ) ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → No @Entity() export class User { @PrimaryGeneratedColumn("uuid") id!: string; @Column("text") name!: string; @CreateDateColumn() createdAt!: Date; } --emitDecoratorMetadata ͕ͳ͍ͷͰ
 खͰܕΛࢦఆ͢ΔͳͲ

Slide 56

Slide 56 text

ྫ: ORM / (de)serialization ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes (هड़͸૿͑Δ) ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → No ‣ ͦ΋ͦ΋શવ strict ͡Όͳ͍͚Ͳɺࠓߋ΍Γ͍ͨʁ @Entity() export class User { @PrimaryGeneratedColumn("uuid") id!: string; // ... } const user = new User(); user.id; // : string, === undefined

Slide 57

Slide 57 text

ྫ: ORM / (de)serialization ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes? (هड़͸૿͑Δ͕) ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → No ‣ ͦ΋ͦ΋શવ strict ͡Όͳ͍͚Ͳɺࠓߋ΍Γ͍ͨʁ ‣ ҆શͳ୅ସखஈ΋͍͘ΒͰ΋͋Δ ‣ Prisma, Drizzle, etc. ‣ Zod, Valibot, etc.

Slide 58

Slide 58 text

ྫ: ϧʔςΟϯάఆٛ ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → No @Controller("users") export class UsersController { @Get() findAll(context: Context, request: Request): Response { /* ... */ } } Ҿ਺σίϨʔλ͸࢖͑ͳ͍ͷͰ
 ݻఆͷҾ਺ʹ͢ΔͳͲ

Slide 59

Slide 59 text

ྫ: ϧʔςΟϯάఆٛ ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → No ‣ Express ͷࠒ͔Β Hono ʹࢸΔ·Ͱ class Λલఏͱ্ͤͣख͍͍ͬͯ͘Δ έʔε͸ଟ͍ Ҿ਺σίϨʔλ͸࢖͑ͳ͍ͷͰ
 ݻఆͷҾ਺ʹ͢ΔͳͲ

Slide 60

Slide 60 text

ྫ: Observable ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → No (޷ΈʹΑΔ) class Checkbox { @observable accessor checked = false; @action toggle(): void { this.checked = !this.checked; } }

Slide 61

Slide 61 text

ྫ: Observable ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → No (޷ΈʹΑΔ) ‣ jotai ͳͲ class Λ࢖Θͳ͍ϥΠϒϥϦ΋͋Δ ‣ ͦ΋ͦ΋ MobX ࣗମ΋ class / σίϨʔλΛ࢖Θͳ͍ํ๏Λ༻ҙ͍ͯ͠Δ

Slide 62

Slide 62 text

ྫ: Web Components ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → No @customElement("my-element") class MyElement extends HTMLElement { // ... }

Slide 63

Slide 63 text

ྫ: Web Components ‣ (1) ݱ࣌఺ͷ࢓༷Ͱ࢖͑Δ΋ͷ͕Ͱ͖Δ͔ → Yes ‣ (2) ຊ౰ʹσίϨʔλΛ࢖͏ඞཁ͕͋Δ͔ → No ‣ ↓ ͱൺ΂ͯಛผخ͍͜͠ͱ͕͋Δ͔ͱ͍͏ͱʁ class MyElement extends HTMLElement { // ... } customElements.define("my-element", MyElement);

Slide 64

Slide 64 text

·ͱΊ

Slide 65

Slide 65 text

·ͱΊ ‣ Q. ͦ΋ͦ΋σίϨʔλͬͯԿʁ ‣ A. ΫϥεͷػೳΛ֦ுͨ͠ΓϝλσʔλΛ෇༩ͨ͠Γ͢Δ΍ͭɻؔ਺ʹ͓ ͚Δߴ֊ؔ਺ʹ૬౰ ‣ Q. --experimentalDecorators ͔ΒͲ͏มΘͬͨͷʁ ‣ A. class fi elds ͷαϙʔτͳͲجຊతʹ͸ਖ਼౷ਐԽͰɺ࠷దԽʹ΋༏͘͠ ͳͬͨɻͨͩ͠Ҿ਺σίϨʔλ΍ --emitDecoratorMetadata ͸ඇରԠ

Slide 66

Slide 66 text

·ͱΊ ‣ Q. ࢓༷΍ΤίγεςϜ͸ࠓͲ͏͍͏ঢ়گʁ ‣ A. ΍΍ݫ͍͠ɻτϥϯεύΠϥܦ༝Ͱ࢖͑͸͢Δ͕ɺΤίγεςϜʹे෼ ૊Έࠐ·ΕΔ·Ͱʹ͸΋͏গ͕͔͔࣌ؒ͠Γͦ͏ ‣ Q. ͿͬͪΌ͚໾ʹཱͭͷʁ ‣ A. ଟ͘ͷϢʔεέʔε͸࣮૷ / ࠶ݱࣗମ͸ՄೳͰɺclass ͷ࢖༻͕ଥ౰ͳΒ ͳ͘΋ͳ͍ɻݱ୅ج४ͰݟΔͱඍົͳέʔε΋͋ΔͷͰ஫ҙ ‣ (ͳΜΒ͔໘ന͍࢖͍ํ͕͋ͬͨΒγΣΞ͍ͯͩ͘͠͞)

Slide 67

Slide 67 text

Appendix

Slide 68

Slide 68 text

ࢀߟจݙ (1/4) ‣ ֤࢓༷ͷఏҊ ‣ https://github.com/tc39/proposal-decorators ‣ https://github.com/tc39/proposal-decorator-metadata ‣ https://github.com/tc39/proposal-class-method-parameter-decorators ‣ https://github.com/tc39/proposal-function-and-object-literal-element- decorators

Slide 69

Slide 69 text

ࢀߟจݙ (2/4) ‣ https://github.com/tc39/notes ‣ TC39 ͷٞࣄ࿥ ‣ https://github.com/tc39/proposals ͷ README ʹؔ࿈͢Δٞࣄ࿥΁ͷϦϯ Ϋ͕͋ΔͷͰɺͦ͜Λى఺ʹಡΉͷ͕͓͢͢Ί ‣ https://github.com/tc39/test262/pull/4103 ‣ Test262 ΁ͷ Decorators / Decorator Metadata ͷ௥Ճ ‣ https://github.com/tc39/proposal-decorators/issues/476 ‣ ༗ࢤʹΑΔ࣮૷ঢ়گͷτϥοΩϯά

Slide 70

Slide 70 text

ࢀߟจݙ (3/4) ‣ ֤ϥΠϒϥϦ / ϑϨʔϜϫʔΫͷରԠঢ়گ ‣ https://github.com/microsoft/tsyringe/issues/225 ‣ https://github.com/inversify/InversifyJS/issues/1507 ‣ https://github.com/typestack/typedi/issues/1178 ‣ https://github.com/typeorm/typeorm/issues/9862 ‣ https://github.com/nestjs/nest/issues/11414 ‣ https://github.com/microsoft/TypeScript/issues/57533 ‣ Stage 3 Decorators Ͱͷ --emitDecoratorMetadata αϙʔτͷཁ๬

Slide 71

Slide 71 text

ࢀߟจݙ (4/4) ‣ ʮECMAScript Decorators ͷมભͱ࠷ऴతͳ࢓༷ʯ ‣ https://zenn.dev/pixiv/articles/ab9a7d7f654a79 ‣ ʮStage 3 Decorators ͷ͜ͱΛࢥ͍ग़࣌͢ʹಡΉهࣄʯ ‣ https://susisu.hatenablog.com/entry/2026/02/26/135056

Slide 72

Slide 72 text

࣌ܥྻ (࢓༷ଆ) ‣ 2014 ~ 2015 ͝Ζ ࠷ॳظͷఏҊ ‣ (ឯ༨ۂં) ‣ 2022-03 Decorators ͕ Stage 3 ʹ ‣ 2023-05 Decorator Metadata ͕ Stage 3 ʹ

Slide 73

Slide 73 text

࣌ܥྻ (TypeScript ଆ) ‣ 2015-06 TypeScript 1.5 ‣ --experimentalDecorators, --emitDecoratorMetadata ‣ 2022-11 TypeScript 4.9 ‣ Auto-accessors (Decorators ͷҰ෦) ‣ 2023-03 TypeScript 5.0 ‣ Decorators ‣ 2023-08 TypeScript 5.2 ‣ Decorator Metadata