ããªãåºæ¬çã§ãããããªã¢ãŒãã£ãã¯ã§ã¢ã¯ãã£ããªã¬ã³ãŒãã¹ã¿ã€ã«ã¢ãã«ã·ã¹ãã ãå®è£
ããããšãããšãã³ã³ã¹ãã©ã¯ã¿ãŒãŸãã¯ãã³ãã¬ãŒã/ãžã§ããªãã¯ãšçµã¿åãããŠäœ¿çšââãããšãåã·ã¹ãã ãthis
ãå°éããªããšããåé¡ãçºçããŸãã
ããã«ã€ããŠã¯ä»¥åã«ããã«æçš¿ããŸããããïŒ5493ã§ãããïŒ5492ããã®åäœã«ã€ããŠèšåããŠããããã§ãã
ãããŠããããç§ãäœæããSOæçš¿ã§ãïŒ
http://stackoverflow.com/questions/33443793/create-a-generic-factory-in-typescript-unsolved
ãããªãè°è«ã®ããã«ãç§ã®äŸãïŒ5493ãããã®ãã±ããã«ãªãµã€ã¯ã«ããŸããã ãããªããšã話ãåãã®æ°æã¡ãè¡šããªãŒãã³ãã±ããã欲ããã£ãã®ã§ãããä»ã®2ã€ã¯ã¯ããŒãºã§ãã
ããã¯ãã¢ãã«ãçæããã¢ãã«Factory
ã®æŠèŠã瀺ãäŸã§ãã Factory
ããè¿ãããBaseModel
ãã«ã¹ã¿ãã€ãºããå Žåã¯ãããããªãŒããŒã©ã€ãã§ããã¯ãã§ãã ãã ããéçã¡ã³ããŒã§ã¯this
ã䜿çšã§ããªããããããã¯å€±æããŸãã
// Typically in a library
export interface InstanceConstructor<T extends BaseModel> {
new(fac: Factory<T>): T;
}
export class Factory<T extends BaseModel> {
constructor(private cls: InstanceConstructor<T>) {}
get() {
return new this.cls(this);
}
}
export class BaseModel {
// NOTE: Does not work....
constructor(private fac: Factory<this>) {}
refresh() {
// get returns a new instance, but it should be of
// type Model, not BaseModel.
return this.fac.get();
}
}
// Application Code
export class Model extends BaseModel {
do() {
return true;
}
}
// Kinda sucks that Factory cannot infer the "Model" type
let f = new Factory<Model>(Model);
let a = f.get();
// b is inferred as any here.
let b = a.refresh();
ãã¶ãããã®åé¡ã¯ã°ãããŠãããç°¡åãªåé¿çããããŸãã ãã®ãããªãã¿ãŒã³ãã©ã®ããã«å®çŸã§ãããã«ã€ããŠã®ã³ã¡ã³ããæè¿ããŸãã
ç§ã®ããŒãã®ãµã€ãºãšåœ¢ã¯éåžžã«äŒŒãŠããŸãïŒ ã¢ãã€ïŒ
ã¹ãŒããŒã¯ã©ã¹ã®ãã¡ã¯ããªã¡ãœããã¯ããã®ãµãã¯ã©ã¹ã®æ°ããã€ã³ã¹ã¿ã³ã¹ãè¿ããŸãã ç§ã®ã³ãŒãã®æ©èœã¯æ©èœããŸããããªã¿ãŒã³ã¿ã€ãããã£ã¹ãããå¿ èŠããããŸãïŒ
class Parent {
public static deserialize(data: Object): any { ... create new instance ... }
// Can't return a this type from statics! ^^^ :(
}
class Child extends Parent { ... }
let data = { ... };
let aChild: Child = Child.deserialize(data);
// ^^^ Requires a cast as type cannot be inferred.
ä»æ¥ããã®åé¡ã«ééããŸããïŒ
ä¿®æ£ãœãªã¥ãŒã·ã§ã³ã¯ãååãåºæ¬ã¯ã©ã¹ãæ¡åŒµãããžã§ããªãã¯ãšããŠæž¡ãããšã§ããããã¯ãåœé¢ã¯é©çšãããœãªã¥ãŒã·ã§ã³ã§ãã
class Parent {
static create<T extends Parent>(): T {
let t = new this();
return <T>t;
}
}
class Child extends Parent {
field: string;
}
let b = Child.create<Child>();
ãã®åé¡ã解決ãããçç±ã¯ãããŸããïŒ
ç§ã®æèŠã§ã¯ããããéååŠã§ã¯æ©èœããªããšããäºå®ã¯ãåºæ¬çã«ãã®æ©èœãDOAã«ããŸãã ãããŸã§ãã€ã³ã¹ã¿ã³ã¹ã¡ã³ããŒã§ãããå®éã«å¿ èŠãšããããšã¯ãããŸããã§ããããéçãªåŠçã®ã·ã¹ãã ã¯åæã®é ã«å®æããŠãããããéçãªãã®ã«ã€ããŠã¯æ°é±éããšã«å¿ èŠã§ããã ãã®æ©èœãçºè¡šããããšãã¯å€§åã³ã§ãããããã®åŸãã€ã³ã¹ã¿ã³ã¹ã¡ã³ããŒã§ã®ã¿æ©èœããããšã«æ°ä»ãããšãã«å€±æããŸããã
ãŠãŒã¹ã±ãŒã¹ã¯éåžžã«åºæ¬çã§éåžžã«äžè¬çã§ãã åçŽãªãã¡ã¯ããªã¡ãœãããèããŠã¿ãŸãããã
class Animal
{
static create(): this
{
return new this();
}
}
class Bunny extends Animal
{
hop()
{
}
}
Bunny.create().hop() // Type error!! Come on!!
ãã®æç¹ã§ãç§ã¯åç¶æ¿è
ã«static create()
ã¡ãœãããéããã£ã¹ããŸãã¯ãã€æšãŠããããšã«é Œã£ãŠããŸãã ãã®æ©èœããªãããšã¯ãèšèªã®ããªã倧ããªå®å
šæ§ã®ç©Žã®ããã«æããŸãã
@ paul-goåé¡ã¯è§£æ±ºãããŠããŸãã...ïŒ
@ paul-goç§ããã®åé¡ã«äžæºãæããŠããŸããã以äžã¯ç§ãèŠã€ããæãä¿¡é Œã§ããåé¿çã§ãã åAnimalãµãã¯ã©ã¹ã¯ãsuper.createïŒïŒãåŒã³åºããŠãçµæããã®åã«ãã£ã¹ãããå¿ èŠããããŸãã 倧ããããšã§ã¯ãªãããããè¿œå ããããšã§ç°¡åã«åãå€ããã¯ã³ã©ã€ããŒã§ãã
ã³ã³ãã€ã©ãã€ã³ããªã»ã³ã¹ããããŠæãéèŠãªã®ã¯ãããŒããã¹ãŠå¹žãã§ãã
class Animal {
public static create<T extends Animal>(): T {
let TClass = this.constructor.prototype;
return <T>( new TClass() );
}
}
class Bunny extends Animal {
public static create(): Bunny {
return <Bunny>super.create();
}
public hop(): void {
console.log(" Hoppp!! :) ");
}
}
Bunny.create().hop();
\\
\\_ " See? I am now a happy Bunny! "
(') " Don't be so hostile! "
/ )= " :P "
o( )_
@RyanCavanaughãã£ãš...ã©ããããããç§ã¯ãããïŒ5862ãšæ··åããŸãã...æŠæ§ã®æ»ææ§ããè©«ã³ããŸã:-)
@ Think7ãã...ãããã£ãŠããåç¶æ¿è ã®éçãªcreateïŒïŒã¡ãœãããéããã£ã¹ããŸãã¯ãã€æšãŠã«é Œããã ãã ããã©ã€ãã©ãªéçºè ã§ããããšã³ããŠãŒã¶ãŒã«ãç¶æ¿ããã¯ã©ã¹ã«åæå®ãããéçã¡ãœããã®æãå®è£ ããããã«åŒ·å¶ããããšã¯ã§ããŸããã
æ³åŸã ããªãã®ã³ãŒãã®äžã®ãã¹ãŠãå®å šã«éããïŒD
ãããããã ãã®äŸ¡å€ããã£ãããããŒãæãããã«ãªã£ãã
ïŒ+1ïŒãããŒ
ïŒrabbit ïŒïŒ heartïŒ
+1ãééããªããããèŠãã
ãã®ãããã¯ã«é¢ãããã£ã¹ã«ãã·ã§ã³ã®æŽæ°ã¯ãããŸããïŒ
ããã¯ç§ãã¡ã®èšå€§ãªææ¡ã®ããã¯ãã°ã«æ®ã£ãŠããŸãã
Javascriptã¯ãã§ã«ãã®ãããªãã¿ãŒã³ã§æ£ããåäœããŸãã TSãåŸãããšãã§ããã°ãå€ãã®å®åæ/äœåãªã³ãŒãããç§ãã¡ãæãã§ãããã ãã¢ãã«ãã¿ãŒã³ãã¯ããªãæšæºçãªãã®ã§ãJSãããã«å¯ŸããŠè¡ãããã«TSãæ©èœããããšãæåŸ ããŠããŸãã
ãŸããä»ã®äººãšåããCRUDã¢ãã«ãã®çç±ããããã®æ©èœãæ¬åœã«å¿ èŠã§ãã ã€ã³ã¹ã¿ã³ã¹ã¡ãœãããããéçã¡ãœããã§å¿ èŠã§ãã
ããã«ãããïŒ8164ã§èª¬æãããŠããåé¡ã«å¯Ÿããé©åãªè§£æ±ºçãæäŸãããŸãã
ãªãŒããŒã©ã€ããšãžã§ããªãã¯ã䜿çšããããœãªã¥ãŒã·ã§ã³ããããã®ã¯è¯ãããšã§ãããããã§ã¯å®éã«ã¯äœã解決ããŠããŸããããã®æ©èœã䜿çšããç®çã¯ããã®ãããªãªãŒããŒã©ã€ã/ãã£ã¹ããåé¿ãã this
ãè¿ãããæ¹æ³ãšã®äžè²«æ§ãä¿ã€ããšã§ããã¿ã€ãã¯ã€ã³ã¹ã¿ã³ã¹ã¡ãœããã§åŠçãããŸãã
ç§ã¯Sequelize4.0ã®åä»ãã«åãçµãã§ããã Model
ã¯ã©ã¹ããµãã¯ã©ã¹åããã¢ãããŒãã䜿çšããŠããŸãã ãã®Modelã¯ã©ã¹ã«ã¯ã findById()
ãªã©ã®ç¡æ°ã®éçã¡ãœããããããŸãããã¡ããModel
ã¯è¿ããŸããããéçã³ã³ããã¹ãã§ã¯ãµãã¯ã©ã¹ãå¥åthis
ãè¿ããŸãã
abstract class Model {
public static tableName: string;
public static findById(id: number): this { // error: a this type is only available in a non-static member of a class or interface
const rows = db.query(`SELECT * FROM ${this.tableName} WHERE id = ?`, [id]);
const instance = new this();
for (const column of Object.keys(rows[0])) {
instance[column] = rows[0][column];
}
return instance;
}
}
class User extends Model {
public static tableName = 'users';
public username: string;
}
const user = User.findById(1); // user instanceof User
çŸåšããããå
¥åããããšã¯ã§ããŸããã Sequelizeã¯Nodeã®ORMã§ãããå
¥åã§ããªãã®ã¯æ²ããããšã§ãã æ¬åœã«ãã®æ©èœãå¿
èŠã§ãã å¯äžã®æ¹æ³ã¯ããããã®é¢æ°ã®1ã€ãåŒã³åºããã³ã«ãã£ã¹ããããããã¹ãŠã®é¢æ°ããªãŒããŒã©ã€ãããŠãæ»ãå€ã®åã調æŽãã super.method()
ãåŒã³åºã以å€ã«äœãããªãããšã§ãã
ãŸããéçã¡ã³ããŒã¯ãžã§ããªãã¯ååŒæ°ãåç §ã§ããªãããšãé¢ä¿ããŠããŸããäžéšã®ã¡ãœããã¯ãååŒæ°ãä»ããŠåæå®ã§ããã¢ãã«ã®å±æ§ã®ãªããžã§ã¯ããªãã©ã«ãåããŸãããã€ã³ã¹ã¿ã³ã¹ã¡ã³ããŒã®ã¿ã䜿çšã§ããŸãã
ð°ããããŸã ä¿®æ£/è¿œå ãããŠããªãããšãä¿¡ããããšãã§ããŸãã.....
ãããããŸãå©çšããããšãã§ããŸãïŒ
declare class NSObject {
init(): this;
static alloc(): this;
}
declare class UIButton extends NSObject {
}
let btn: UIButton = UIButton.alloc().init();
ãããç§ãåããããŠãŒã¹ã±ãŒã¹ã§ãïŒãããæ¯æããŠéããhttps://github.com/Microsoft/TypeScript/issues/9775ãã移è¡ããŸããïŒ
çŸåšãã³ã³ã¹ãã©ã¯ã¿ãŒã®ãã©ã¡ãŒã¿ãŒã¯this
ã¿ã€ãã䜿çšã§ããŸããã
class C<T> {
constructor(
public transformParam: (self: this) => T // not works
){
}
public transformMethod(self: this) : T { // works
return undefined;
}
}
äºæ³ïŒããã¯ã³ã³ã¹ãã©ã¯ã¿ãŒãã©ã¡ãŒã¿ãŒã§äœ¿çšã§ããŸãã
解決ãæ±ããããŠããåé¡ïŒ
class TheirFluentApi {
totallyUnrelated(): TheirFluentApi {
return this;
}
}
class MyFluentApi<FluentApi> {
constructor(
public toNextApi: (self: this) => FluentApi // let's imagine it works
){
}
one(): FluentApi {
return this.toNextApi(this);
}
another(): FluentApi {
return this.toNextApi(this);
}
}
// self based fluent API;
const selfBased = new MyFluentApi(this => this);
selfBased.one().another();
// foreign based fluent API:
const foreignBased = new MyFluentApi(this => new TheirFluentApi());
foreignBased.one().totallyUnrelated();
å°æ¥ãèŠæ®ããåé¿çïŒ
class Foo {
foo() { }
static create<T extends Foo>(): Foo & T {
return new this() as Foo & T;
}
}
class Bar extends Foo {
bar() {}
}
class Baz extends Bar {
baz() {}
}
Baz.create<Baz>().foo()
Baz.create<Baz>().bar()
Baz.create<Baz>().baz()
ãã®ããã«ãTypeScriptãéçã¡ã³ããŒã«å¯ŸããŠthis
ããµããŒãããŠããå Žåãæ°ãããŠãŒã¶ãŒã³ãŒãã¯Baz.create<Baz>()
$ã§ã¯ãªãBaz.create()
ã«ãªããŸãããå€ããŠãŒã¶ãŒã³ãŒãã¯åé¡ãªãæ©èœããŸãã ïŒç¬é¡ïŒ
ããã¯æ¬åœã«å¿ èŠã§ãïŒ ç¹ã«ãã€ã³ã¹ã¿ã³ã¹ãè¿ãéçã¡ãœãããæã€DAOã®å Žåã ãããã®ã»ãšãã©ã¯ãïŒä¿åãååŸãæŽæ°ãªã©ïŒã®ããã«ããŒã¹DAOã§å®çŸ©ãããŠããŸã
éçã¡ãœããã®this
åããã¯ã©ã¹ã®åã§ã¯ãªãããããå«ãŸããã¯ã©ã¹ã«è§£æ±ºããããããæ··ä¹±ãçããå¯èœæ§ããããšèšããŸãïŒã€ãŸãã typeof
ïŒã
å®éã®JSã§ã¯ãåã«å¯ŸããŠéçã¡ãœãããåŒã³åºããšãé¢æ°å
ã®this
ãã¯ã©ã¹ã§ããããã®ã€ã³ã¹ã¿ã³ã¹ã§ã¯ãªããããäžè²«æ§ããªããªããŸãã
ãããã人ã
ã®çŽæã§ã¯ãéçã¡ãœããã§this
ã®æ»ãåãèŠããšãã«æåã«ãããã¢ããããã®ã¯ãã€ã³ã¹ã¿ã³ã¹åã ãšæããŸã...
@shlomiassafããã¯ççŸããªãã§ãããã Userãªã©ã®é¢æ°ã®æ»ãåãšããŠã¯ã©ã¹ãæå®ãããšãæ»ãåã¯ãŠãŒã¶ãŒã®ã€ã³ã¹ã¿ã³ã¹ã«ãªããŸãã ãŸã£ããåãã§ãããéçã¡ãœããã§thisã®æ»ãåãå®çŸ©ãããšãæ»ãåã¯thisã®ã€ã³ã¹ã¿ã³ã¹ïŒã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ïŒã«ãªããŸãã ã¯ã©ã¹èªäœãè¿ãã¡ãœããã¯ãtypeofthisã§ã¢ãã«åã§ããŸãã
@felixfbeckerããã¯å®å šã«èŠç¹ã®ããšã§ããããã¯ããªãããããèŠãæ¹æ³ã§ãã
JSã§äœãèµ·ãã£ãŠãããã調ã¹ãŠãããžãã¯ãæšæž¬ã§ããããã«ããŸãã
class Example {
myFunc(): this {
return this;
}
static myFuncStatic(): this {
return this; // this === Example
}
}
new Example().myFunc() // instanceof Exapmle === true
Example.myFuncStatic() // === Example
ããŠãå®éã®å®è¡æã®this
ã¯é¢æ°ã®å¶éãããã³ã³ããã¹ãã§ããããã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã®ãããªæµæ¢ãªAPIã§çºçããããšãšãŸã£ããåãã§ããããã®æ©èœã¯ãJSã®åäœãšäžèŽããé©åãªåãè¿ãããšã§åœ¹ç«ã¡ãŸãã this
ãè¿ãåºæ¬ã¯ã©ã¹ã¯ã掟çã¯ã©ã¹ã«ãã£ãŠäœæãããã€ã³ã¹ã¿ã³ã¹ãè¿ããŸãã ãã®æ©èœã¯å®éã«ã¯ä¿®æ£ãããŠããŸãã
ç·æ¬ããïŒ
ãããã¿ã€ãïŒã€ã³ã¹ã¿ã³ã¹ïŒã®äžéšãšããŠå®çŸ©ãããŠããthis
ãè¿ãã¡ãœããã¯ãã€ã³ã¹ã¿ã³ã¹ãè¿ãããšãæåŸ
ãããŠããŸãã
ãã®ããžãã¯ãç¶ãããšãã¯ã©ã¹åïŒãããã¿ã€ãïŒã®äžéšãšããŠå®çŸ©ãããŠããthis
ãè¿ãã¡ãœããã¯ãã¯ã©ã¹åã§ããå¢çä»ãã³ã³ããã¹ããè¿ãããšãæåŸ
ãããŸãã
ç¹°ãè¿ããŸãããåèŠãæèŠãåçŽãªäºå®ã¯ãããŸããã
çŽæçã«ã¯ãéçé¢æ°ããè¿ãããthis
ã¯ãåå
ã§å®çŸ©ãããŠãããããã€ã³ã¹ã¿ã³ã¹ãè¡šãã®ãå¿«é©ã§ãããããã¯ç§ã§ãã ä»ã®äººã¯éã£ãèãæ¹ããããããããŸããããããŠç§éã¯åœŒãã«åœŒãã®ééã£ãããšãèšãããšãã§ããŸããã
åé¡ã¯ãã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ãè¿ãéçã¡ãœãããšã¯ã©ã¹èªäœãè¿ãéçã¡ãœããïŒãã®ã¿ã€ãïŒã®äž¡æ¹ãå ¥åã§ããå¿ èŠãããããšã§ãã ããªãã®ããžãã¯ã¯JSã®èŠ³ç¹ããã¯çã«ããªã£ãŠããŸãããããã§ã¯return _types_ã«ã€ããŠè©±ããTypeScriptããã®ä»ã®èšèªã§ã¯ã©ã¹ãreturn typeïŒããã§ã¯thisïŒãšããŠäœ¿çšãããšãåžžã«ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãæå³ããŸãã å®éã®ã¯ã©ã¹ãè¿ãããã«ãtypeofæŒç®åããããŸãã
@felixfbeckerããã¯å¥ã®åé¡ãåŒãèµ·ãããŸãïŒ
ã¿ã€ãthis
ãã€ã³ã¹ã¿ã³ã¹ã¿ã€ãã®å Žåãéçã¡ãœããã®æ¬äœã§this
ããŒã¯ãŒããåç
§ããŠãããã®ãšã¯ç°ãªããŸãã return this
ã¯ãé¢æ°ã®æ»ãåtypeof this
ãçæããŸãããããã¯ãŸã£ããå¥åŠãªããšã§ãã
ããããã¡ãããŸãã 次ã®ãããªã¡ãœãããå®çŸ©ããå Žå
getUser(): User {
...
}
Userã¯ã©ã¹ã§ã¯ãªããUser _instance_ãåãæ»ãããšãæåŸ
ããŠããŸãïŒãããtypeof
ã®ç®çã§ãïŒã ããã¯ããã¹ãŠã®åæå®ãããèšèªã§ã©ã®ããã«æ©èœãããã§ãã ã¿ã€ãã»ãã³ãã£ã¯ã¹ã¯ãã©ã³ã¿ã€ã ã»ãã³ãã£ã¯ã¹ãšã¯åçŽã«ç°ãªããŸãã
this
ãŸãã¯static
ããŒã¯ãŒãããåã¯ã©ã¹ã§æäœããããã®funcã®ã³ã³ã¹ãã©ã¯ã¿ãŒãšããŠäœ¿çšããŠã¿ãŸãããïŒ
class Model {
static find():this[] {
return [new this("prop")]; // or new static(...)
}
}
class Entity extends Model {
constructor(public prop:string) {}
}
Entity.find().map(x => console.log(x.prop));
ãããŠããããJSã®äŸãšæ¯èŒãããšãæ£ããæ©èœããããšãããããŸãã
class Model {
static find() {
return [new this]
}
}
class Entity extends Model {
constructor(prop) {
this.prop = prop;
}
}
Entity.find().map(x => console.log(x.prop))
éçã¡ãœããã§this
ã¿ã€ãã䜿çšããããšã¯ã§ããŸãããããããåé¡ã®æ ¹æ¬çãªåå ã ãšæããŸãã
@felixfbecker
ãã®ããšãèæ ®ïŒ
class Greeter {
static getHandle(): this {
return this;
}
}
ãã®åã¢ãããŒã·ã§ã³ã¯çŽæçã§ãããéçã¡ãœããã®åthis
ãã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ã§ããå Žåã¯æ£ãããããŸããã ããŒã¯ãŒãthis
ã¯ãéçã¡ãœããã§typeof this
ã®ã¿ã€ããæã£ãŠããŸãïŒ
this
ã¯ãã¯ã©ã¹ã¿ã€ãã§ã¯ãªããã€ã³ã¹ã¿ã³ã¹ã¿ã€ããåç
§ããå¿
èŠããããšæããŸããããã¯ãã€ã³ã¹ã¿ã³ã¹ã¿ã€ãïŒ typeof X
ïŒããã¯ã©ã¹ã¿ã€ããžã®åç
§ãååŸã§ãããããã®éã¯ã§ããªãããã§ãïŒ instancetypeof X
ïŒïŒ
@xealotããããŸããã代ããã«$ static
ããŒã¯ãŒãã䜿çšããŠã¿ãŸãããïŒ this
ïŒ ãã ããJSéçã³ã³ããã¹ãã®this
ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒãæããŸãã
@izatopã¯ããçæãããjavascriptã¯ïŒé©åãŸãã¯äžé©åã«ïŒæ©èœããŸãã ãã ããããã¯Javascriptã«é¢ãããã®ã§ã¯ãããŸããã äžæºã¯ãJavascriptèšèªããã®ãã¿ãŒã³ãèš±å¯ããŠããªããšããããšã§ã¯ãªããTypescriptã®åã·ã¹ãã ãèš±å¯ããŠããªããšããããšã§ãã
Typescriptã¯éçã¡ã³ããŒã§ããªã¢ãŒãã£ãã¯ãªthis
åãèš±å¯ããªãããããã®ãã¿ãŒã³ã§ã¯åã®å®å
šæ§ãç¶æã§ããŸããã ããã«ã¯ã static
ããŒã¯ãŒããšconstructor
ã§å®çŸ©ãããã¯ã©ã¹ã¡ãœãããå«ãŸããŸãã
@LPGhatguyã§ãããããªãã¯ç§ã®åã®ã³ã¡ã³ããèªã¿ãŸããããïŒïŒ æ»ãåãUser
ã®ã¡ãœãããããå Žåã return User;
return new User();
ãæåŸ
ããŸãã åæ§ã«ãæ»ãå€this
$ã¯ãéçã¡ãœããã®return new this();
ãæå³ããŸãã ééçã¡ãœããã§ã¯ããã¯ç°ãªããŸããã this
ã¯åžžã«ãªããžã§ã¯ãã§ãããããã€ã³ã¹ã¿ã³ã¹åããããšã¯ã§ããŸããã ããããæçµçã«ã¯ããããtypeof
ã®ããã«æè¯ã®æ§æã§ããããã®æ©èœãTSã§éåžžã«å¿
èŠã§ããããšã«åºæ¬çã«åæããŸãã
@xealot TypeScriptã§å€æ
çãªthis
ãèš±å¯ãããŠããªãããšãç解ããŸãããããã®æ©èœãTSã«è¿œå ããªãçç±ããèãããŸãã
ãã®åé¡ã®ãã¹ãŠã®ãŠãŒã¹ã±ãŒã¹ã§æ¬¡ã®ããšãæ©èœãããã©ããã¯ããããŸããããéçã¡ãœããã§this:
åã䜿çšããåæšè«ã·ã¹ãã ãã¹ããŒãã«äœ¿çšãããšã楜ãã¿ãåŸãããããšãããããŸãããã¿ã€ãã³ã°ã ä¿¡ããããªãã»ã©èªã¿ããããšã¯èšããªããããããŸããããåã¯ã©ã¹ã®éçã¡ãœãããåå®çŸ©ããªããŠãæ©èœããŸãã
[email protected]ã§åäœããŸã
次ã®ããšãèæ ®ããŠãã ããã
// IModelClass is just here to describe an instanciator
// since we can't use typeof T (unfortunately) with
// the generic type system.
interface IModelClass<T extends Model> {
new (...a: any[]): T
// unfortunately, we have to put here again all the typing information
// of the static members (without static, since we are describing a class, not an instance)
some_member: string
create<T extends Model>(this: IModelClass<T>): T
}
class Model {
// Here we use this with the IModel<T> to force the
// type system to use T as our current caller.
static some_member: string
// When we call Dog.create() below, T is thus resolved
// to Dog *and stays that way*
// If typeof worked on generic types (it doesn't), we could have defined this method
// instead as
// static create<T extends Model>(this: typeof T): T { ... }
static create<T extends Model>(this: IModelClass<T>): T {
return new this() // whatever you fancy here
}
}
class Dog extends Model {
bark() { }
}
class Cat extends Model {
meow() { }
}
// Everything should be typed here, and we didn't have to redefine static methods
// in Dog nor Cat
let dog = Dog.create()
dog.bark()
let cat = Cat.create()
cat.meow()
@ceymardãªãthis
ããã©ã¡ãŒã¿ãšããŠæå®ãããŠããã®ã§ããïŒ
ããã¯ã httpsïŒ//github.com/Microsoft/TypeScript/issues/3694ã«ä»å±ããŠããtypescript 2.0.0ãåå ã§ãé¢æ°ã®thisãã©ã¡ãŒã¿ãŒãå®çŸ©ã§ããŸãïŒãããã£ãŠãæ¬äœã§this
ã䜿çšããã«äœ¿çšã§ããŸãïŒåé¡ãšæ©èœã®èª€ã£ã䜿çšãé²ãããã«ïŒ
éçã¡ãœããã ãã§ãªãã¡ãœããã§ã䜿çšã§ããããšãããããŸããããŸããæäŸããthis
ãæ¯èŒããããã«åŒ·å¶ããããšã§ãåæšè«æ©èœããæ¯æŽããããªã©ãéåžžã«é¢çœããã®ãå¯èœã«ãªããŸãã ïŒIModelT
ã®æ£ããåããæšæž¬ãããŠäœ¿çšããé¢æ°ãæ£ããå
¥åããŸãã
ïŒ this
ã¯typescriptã³ã³ãã€ã©ã«ãã£ãŠç解ããã_special_ãã©ã¡ãŒã¿ã§ãããé¢æ°ã«ãã1ã€è¿œå ãããªãããšã«æ³šæããŠãã ããïŒ
æ§æã¯<this extends Whatever>
ã®ãããªãã®ã ãšæããŸããã ããã§ã create()
ã«ä»ã®ãã©ã¡ãŒã¿ãããå Žåã§ããããã¯æ©èœããŸããïŒ
絶察
ãŸããããã¯çµã¿èŸŒã¿åã«ãšã£ãŠéèŠã§ããããšãææããããšæããŸãã
ããšãã°ã Array
ããµãã¯ã©ã¹åãããšããµãã¯ã©ã¹ã®from()
ã¡ãœããã¯ã Array
ã§ã¯ãªãããµãã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãè¿ããŸãã
class Task {}
class TaskList extends Array<Task> {
public execute() {}
}
// actually returns instance of TaskList at runtime
const tasks = TaskList.from([new Task()])
tasks.execute() // error, method execute does not exist on type Array
ãã®åé¡ã«é¢ããæŽæ°ã¯ãããŸããïŒ ãã®æ©èœã¯ãTypeScriptã«é¢ããç§ã®ããŒã ã®çµéšãå€§å¹ ã«åŒ·åããŸãã
ããã¯ORMã§äžè¬çã«äœ¿çšããããã¿ãŒã³ã§ãããå€ãã®ã³ãŒãã¯ã³ã³ãã€ã©ãåã·ã¹ãã ãæ³å®ãããã®ãšã¯å€§ããç°ãªãåäœããããããããã¯ããªãéèŠã§ããããšã«æ³šæããŠãã ããã
ç§ã¯å察ã®è°è«ã«å¯ŸããŠããã€ãã®å察ã®è°è«ãæèµ·ããã§ãããã
@shlomiassafãææããããã«ãéçã¡ã³ããŒã§this
ãèš±å¯ãããšã this
ã¯éçã¡ãœãããšã€ã³ã¹ã¿ã³ã¹ã¡ãœããã§ç°ãªãããšãæå³ãããããæ··ä¹±ãçããŸãã ããã«ãåã¢ãããŒã·ã§ã³ã®this
this
ã®ã»ãã³ãã£ã¯ã¹ã¯ç°ãªããŸãã æ°ããããŒã¯ãŒããå°å
¥ããããšã§ãã®æ··ä¹±ãé¿ããããšãã§ããŸãããæ°ããããŒã¯ãŒãã®ã³ã¹ãã¯é«ããªããŸãã
ãŸããçŸåšã®TypeScriptã«ã¯ç°¡åãªåé¿çããããŸãã @ceymardã¯ãã§ã«ããã瀺ããŠããŸãã ãããŠãéçã¡ãœããã®å®è¡æã»ãã³ãã£ã¯ã¹ããã£ããã£ããã®ã§ã圌ã®ã¢ãããŒãã奜ã¿ãŸãã ãã®ã³ãŒããæ€èšããŠãã ããã
class A {
constructor() {}
static create<T extends A>(this: {new (): T}) {} // constructor signature is exactly the same as A's
}
class B extends A {
constructor(a: number) {
super()
}
}
B.create() // correctly trigger compile error here
å€æ
æ§ããµããŒããããŠããå Žåãã³ã³ãã€ã©ã¯class B extends A
ã§ãšã©ãŒãå ±åããå¿
èŠããããŸãã ããããããã¯é倧ãªå€åã§ãã
@HerringtonDarkholmeæ··ä¹±ã¯èŠãããŸãããæ»ãå€ã®ã¿ã€ãã¯ã this
ã§ã return new this()
ã«æåŸ
ãããã®ãšãŸã£ããåãã§ãã ãã®ããã«self
ã䜿çšããããšãã§ããŸãããå¥ã®ããŒã¯ãŒãïŒåºåã®çæã«äœ¿çšããããã®ä»¥å€ïŒãå°å
¥ããæ¹ãæ··ä¹±ããããããã§ãã ãã§ã«ãªã¿ãŒã³ã¿ã€ããšããŠäœ¿çšããŠããŸãããå¯äžã®ïŒããã倧ããªïŒåé¡ã¯éçã¡ã³ããŒã§ã¯ãµããŒããããŠããªãããšã§ãã
ã³ã³ãã€ã©ãŒã¯ããã°ã©ããŒã«åé¿çãèŠæ±ããã¹ãã§ã¯ãããŸãããTypeScriptã¯ãæ¡åŒµJavaScriptãã§ãããšæ³å®ãããŠããããã®å Žåã¯åœãŠã¯ãŸããŸãããã³ãŒããäœçŸäžãã®ãšã©ãŒãçæããªãããã«ãè€éãªåé¿çãå®è¡ããå¿ èŠããããŸãã ã©ããããããçŸåšã®ããŒãžã§ã³ã§ãããéæã§ããã®ã¯çŽ æŽãããããšã§ãããããã¯ãããåé¡ãªããä¿®æ£ãå¿ èŠãšããªããšããæå³ã§ã¯ãããŸããã
ã§ã¯ããªãthis
ã®æ»ãåãã¡ãœããæ¬äœã®this
ã®åãšç°ãªãã®ã§ããããã
ãã®ã³ãŒãã倱æããã®ã¯ãªãã§ããïŒ ãããæ°åè
ã«ã©ã®ããã«èª¬æã§ããŸããïŒ
class A {
static create(): this {
return this
}
}
JavaScriptã®ã¹ãŒããŒã»ããããããåãå ¥ããããªãã®ã¯ãªãã§ããïŒ
class A {
static create() {
return new this()
}
}
abstract class B extends A {}
確ãã«ãå¥ã®ããŒã¯ãŒããå°å
¥ããå¿
èŠããããããããŸããã self
ããŸãã¯instance
ã®å¯èœæ§ããããŸã
@HerringtonDarkholmeãããç§ãæ°åè
ã«ããã説æããæ¹æ³ã§ãã
ããªãããããšã
class A {
static whatever(): B {
return new B();
}
}
B
ã®æ»ãã¿ã€ãã¯ã B
ã®ã€ã³ã¹ã¿ã³ã¹ãè¿ãå¿
èŠãããããšãæå³ããŸãã ã¯ã©ã¹èªäœãè¿ãããå Žåã¯ã次ã䜿çšããå¿
èŠããããŸã
class B {
static whatever(): typeof B {
return B;
}
}
ããã§ãJavaScriptã®å Žåãšåæ§ã«ãéçã¡ã³ããŒã®this
ã¯ã¯ã©ã¹ãåç
§ããŸãã ãããã£ãŠãéçã¡ãœããã§this
ã®æ»ãåã䜿çšããå Žåã¯ãã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãè¿ãå¿
èŠããããŸãã
class A {
static whatever(): this {
return new this();
}
}
ã¯ã©ã¹èªäœãè¿ãããå Žåã¯ã typeof this
ã䜿çšããå¿
èŠããããŸãïŒ
class A {
static whatever(): typeof this {
return this;
}
}
ããã¯ãŸãã«ãTSã§ã¿ã€ãããã§ã«æ©èœããŠããæ¹æ³ã§ãã ã¯ã©ã¹ã䜿çšããŠå
¥åããå ŽåãTSã¯ã€ã³ã¹ã¿ã³ã¹ãäºæããŸãã ã¯ã©ã¹ã¿ã€ãèªäœãå
¥åããå Žåã¯ã typeof
ã䜿çšããå¿
èŠããããŸãã
次ã«ã this
ãã¡ãœããæ¬äœã§åãæå³ãæããªãçç±ãå°ããŸãã ã€ã³ã¹ã¿ã³ã¹ã¡ãœããã®åã¢ãããŒã·ã§ã³ã®this
ãã察å¿ããã¡ãœããæ¬äœã®this
ãšåãæå³ãæã€å Žåãéçã¡ãœããã§ã¯åãã§ã¯ãªãã®ã¯ãªãã§ããïŒ
ç§ãã¡ã¯ãžã¬ã³ãã«çŽé¢ããŠããã3ã€ã®éžæè¢ããããŸãã
this
ã¯ãããŸããŸãªã³ã³ããã¹ãã§ããŸããŸãªããšãæå³ããŸãïŒæ··ä¹±ïŒself
ãstatic
ãªã©ã®æ°ããããŒã¯ãŒããå°å
¥ãã3çªç®ã®ã¢ãããŒãã¯ãéçã¡ãœããå®çŸ©ã®å®è¡æã»ãã³ãã£ã¯ã¹ãåæ ããŠãããããç§ã¯3çªç®ã®ã¢ãããŒãã奜ã¿ãŸãã
ãŸãããµã€ããå®çŸ©ããã®ã§ã¯ãªãã䜿çšãµã€ãã®ãšã©ãŒãç¹å®ããŸããã€ãŸãããã®ã³ã¡ã³ãã®ããã«ããšã©ãŒã¯class B extends A
B.create
ã§å ±åãããŸãã ãã®å Žåã䜿çšãµã€ããšã©ãŒã¯ããæ£ç¢ºã§ãã ïŒ this
ãåç
§ããéçã¡ãœããã宣èšããŠãããæœè±¡ãµãã¯ã©ã¹ã宣èšããããšãæ€èšããŠãã ããïŒã
ãããŠãæãéèŠãªããšã¯ãæ°æ©èœã®ããã®èšèªææ¡ãå¿ èŠãšããªãããšã§ãã
確ãã«å¥œã¿ã¯äººãšã¯ç°ãªããŸãã ããããå°ãªããšãç§ã¯ãã®ãããªãã詳现ãªææ¡ãèŠãããšæã£ãŠããŸãã æœè±¡ã¯ã©ã¹ã®å²ãåœãŠå¯èœæ§ããµãã¯ã©ã¹ã®äºææ§ã®ãªãã³ã³ã¹ãã©ã¯ã¿ãŒã·ã°ããã£ããšã©ãŒã¬ããŒãæŠç¥ãªã©ã解決ãã¹ãåé¡ã¯ãããããããŸãã
@HerringtonDarkholmeã€ã³ã¹ã¿ã³ã¹ã¡ãœããã®å Žåãã©ã³ã¿ã€ã this
ã¯ãªããžã§ã¯ãã€ã³ã¹ã¿ã³ã¹ã§ãããã¯ã©ã¹ã§ã¯ãªããããæ··ä¹±ããäœå°ã¯ãããŸããã ã¿ã€ãthis
ãæåéãã©ã³ã¿ã€ã this
ã§ããããšã¯æããã§ãããä»ã®ãªãã·ã§ã³ã¯ãããŸããã éçãªå Žåã¯ããªããžã§ã¯ãæåããã°ã©ãã³ã°èšèªã®ä»ã®ã¯ã©ã¹ã¢ãããŒã·ã§ã³ãšåãããã«åäœããŸããã¯ã©ã¹ã§ã¢ãããŒã·ã§ã³ãä»ãããšãã€ã³ã¹ã¿ã³ã¹ãæ»ã£ãŠããããšãæåŸ
ãããŸãã ããã«ãTSã®å ŽåãJavaScriptã¯ã©ã¹ããªããžã§ã¯ãã§ãããããã¯ã©ã¹ãtypeof
ãšå
¥åãããšããªãã©ã«ã¯ã©ã¹ãè¿ãããŸãã
ã€ãŸããéçã±ãŒã¹ã«ã€ããŠãèããããã«this
ãªã¿ãŒã³åãå®è£
ãã代ããã«ãŠãŒã¶ãŒã«ã€ã³ã¹ã¿ã³ã¹ã¡ãœããçšã«åžžã«typeof this
ãèšè¿°ããããã«èŠæ±ãããšãã¯ãããããããäžè²«æ§ããã£ãã§ãããã ãããããã®æ±ºå®ã¯åœæè¡ãããã®ã§ãä»ããäœæ¥ããå¿
èŠããããŸããç§ãèšã£ãããã«ãã€ã³ã¹ã¿ã³ã¹ã¡ãœããã®this
ã¯ä»ã®ã¿ã€ããçæããªããããæ··ä¹±ã®äœå°ã¯ãããŸããïŒã¯ã©ã¹ãšã¯ç°ãªããéçåãšã€ã³ã¹ã¿ã³ã¹åããããŸãïŒã®ã§ããã®å Žåã¯åºå¥ããã誰ããæ··ä¹±ããããšã¯ãããŸããã
OKã this
ã§èª°ãæ··ä¹±ããªããšä»®å®ããŸãããã æœè±¡ã¯ã©ã¹ã®å²ãåœãŠå¯èœæ§ã¯ã©ãã§ããïŒ
ã¡ãœããã®éçæ§ã¯ããæ£æçã§ãã ãã¹ãŠã®é¢æ°ã¯ããããã£ãšã¡ãœãããæã€ããšãã§ããŸãã new
ã§ãåŒã³åºãããšãã§ããå Žåã¯ããããã®ããããã£ãšã¡ãœãããstatic
ãšåŒã¶ããšã«ããŸãã çŸåšããã®èŠåã¯ECMAScriptã«ãã£ãããšçµã¿èŸŒãŸããŠããŸãã
@HerringtonDarkholme this
ã䜿çšãããšæ··ä¹±ãçããããšã¯ééããããŸããã ãã ãã this
ã®äœ¿çšã«ã€ããŠã¯äœãééãããªãã®ã§ãç¹ã«ããŸããŸãªä»£æ¿æ¡ã®éæãªè²»çšäŸ¿çåæãèæ
®ãããšããŸã£ããåé¡ãªããšæããŸãã this
ãæãæªãéžæè¢ã§ã¯ãªããšæããŸãã
ç§ã¯å ã®æçš¿ãããã®ã¹ã¬ããã«è¿œãã€ãããšãè©Šã¿ãŸãããå€åããã¯å°ãè»éããå€ããããã«æããŸãã
æ確ã«ããããã«ãã³ã³ã¹ãã©ã¯ã¿ãŒã§ãç¹ã«ãžã§ããªãã¯/ãã³ãã¬ãŒããšããŠäœ¿çšãããå Žåã this
åã¢ãããŒã·ã§ã³ãå€åœ¢ã§ããããšãæãŸããŸãã @shlomiassafãš@HerringtonDarkholmeã«é¢ããŠã¯ã static
ã¡ãœããã䜿çšããäŸã¯æ··ä¹±ãæãå¯èœæ§ãããããã®åé¡ã®æå³ã§ã¯ãªããšæããŸãã
ãã®ããã«èããããããšã¯ããŸããããŸããããã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯éçã§ãã ãã®äŸïŒããæ確ãªã³ã¡ã³ãã§åæçš¿ããŸãïŒã¯ãéçã¡ãœããã§this
ã宣èšããŠããŸããã代ããã«ãéçã¡ãœããã®åã¢ãããŒã·ã§ã³ã®ãžã§ããªãã¯ãä»ããŠå°æ¥äœ¿çšããããã«this
ã宣èšããŠããŸãã ã
éãã¯ãéçã¡ãœããã§this
ãããã«èšç®ããããªãã®ã§ãããå°æ¥çã«ã¯åçã¡ãœããã§èšç®ããããšããããšã§ãã
// START LIBRARY CODE
// Constrains the constructor to one that creates things that extend from BaseModel
interface ModelConstructor<T extends BaseModel> {
new(fac: ModelAPI<T>): T;
}
class ModelAPI<T extends BaseModel> {
// skipping the use of a ModelConstructor in favor of typeof does not work
// constructor(private modelType: typeof T) {}
constructor(private modelType: ModelConstructor<T>) {}
create() {
return new this.modelType(this);
}
}
class BaseModel {
// This is where "polymorphic `this`" in static members matters. We are
// trying to say that the ModelAPI should create instances of whatever
// the *current* class is, not the BaseModel class. Much like it would
// at runtime.
constructor(private fac: ModelAPI<this>) {}
reload() {
// `reload()` returns a new instance of type Any, incorrect
return this.fac.create();
}
}
// END LIBRARY CODE
// START APPLICATION CODE
// Create a custom model class with custom behavior
class Model extends BaseModel {}
// Create an instance of the model API that produces my custom type
let api = new ModelAPI<Model>(Model); // ModalAPI should be able to infer "<Model>" from the constructor?
let modelInst = api.create(); // Returns type of Model, correct
let reset = modelInst.reload(); // Returns type of Any, incorrect
// END APPLICATION CODE
ãããçŽãããããšæã人ã«ã¯ããŸããããã¯éåžžã«ç°¡åã§ã¯ãªãããšã«åæããŸãã ãã ãã BaseModel
ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã§ã®this
ã®äœ¿çšã¯ãå®éã«ã¯éçãªäœ¿çšã§ã¯ãªããåŸã§èšç®ããã延æããã䜿çšã§ãã ãã ããéçã¡ãœããïŒã³ã³ã¹ãã©ã¯ã¿ãŒãå«ãïŒã¯ãã®ããã«ã¯åäœããŸããã
å®è¡æã«ãããã¯ãã¹ãŠæåŸ ã©ããã«æ©èœãããšæããŸãã ãã ããåã·ã¹ãã ã§ã¯ããã®ç¹å®ã®ãã¿ãŒã³ãã¢ãã«åããããšã¯ã§ããŸããã typescriptãjavascriptãã¿ãŒã³ãã¢ãã«åã§ããªãããšãããã®åé¡ãæªè§£æ±ºã§ããçç±ã®æ ¹æ ã§ãã
ãããçŽããããã³ã¡ã³ãã§ããå Žåã¯ç³ãèš³ãããŸããããæ¥ãã§æžãããŠããŸãã
@xealotç§ã¯ããªãã®äž»åŒµãç解ããŸããããéçã¡ãœããã®å€åœ¢this
ãå
·äœçã«ç€ºåããä»ã®åé¡ã¯ãããã®è€è£œãšããŠã¯ããŒãºãããŸããã TSã®ä¿®æ£ã«ãããäž¡æ¹ã®ãŠãŒã¹ã±ãŒã¹ãæå¹ã«ãªããšæããŸãã
ããªãã®æ£ç¢ºãªãŠãŒã¹ã±ãŒã¹ã¯äœã§ããïŒ ãã¶ããããã®ããœãªã¥ãŒã·ã§ã³ã§ååã§ãã
ã«ã¹ã¿ã ORMã©ã€ãã©ãªã§äœ¿çšããŠæåããŸãã
ã«ãžã¥ã 10æ20æ¥ 2016à 19ïŒ15ãTom [email protected] a
écritïŒ
ããã¯äžè¬çã«äœ¿çšããããããããªãéèŠã§ããããšã«æ³šæããŠãã ãã
ORMã®ãã¿ãŒã³ãšå€ãã®ã³ãŒãã¯ã
ã³ã³ãã€ã©ãšåã·ã¹ãã ã¯ãããã¹ãã ãšèããŠããŸããâ
ããªããèšåãããã®ã§ãããªãã¯ãããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/Microsoft/TypeScript/issues/5863#issuecomment -255169194ã
ãŸãã¯ã¹ã¬ããããã¥ãŒãããŸã
https://github.com/notifications/unsubscribe-auth/AAtAoRHc45B386xdNhuCLB8iW6i82e7Uks5q16GzgaJpZM4GsmOH
ã
@ceymardãš@HerringtonDarkholmeã«æè¬ããŸãã
static create<T extends A>(this: {new (): T}) { return new this(); }
ã¯ç§ã®ããã«ããªãã¯ãããŸããð
äžèŠstatic create(): this { return new this(); }
ããããããã«ããã§ãããå°ãªããšãæ£ããã§ãïŒ éçã¡ãœããå
ã®this
ã®ã¿ã€ããæ£ç¢ºã«ãã£ããã£ããŸãã
ãããæãè³æãŸãã¯ã³ã¡ã³ããããŠããªãå Žåã§ãããããäœããã®åœ¢ã§åªå ãããããšãé¡ã£ãŠããŸããããšãã°ãæ£ããåãååŸããããã«ååŒæ°ã䜿çšããå¿ èŠãããã®ã¯éåžžã«é¢åã§ãã
let u = User.create<User>();
ãã è¡ãããšãå®éã«å¯èœã§ãããšãïŒ
let u = User.create();
ãŸããstaticãã€ã³ã¹ã¿ã³ã¹ã¿ã€ããåç §ããããšã¯é¿ããããŸããã
éçã¡ã³ããŒã®this
åãã¯ã©ã¹ã®éçåŽã®åã«ããããã€ã³ã¹ã¿ã³ã¹åŽã®åã«ãããã«ã€ããŠãå¥ã®èãããããŸããã this
ã¯éçãªåŽé¢ã§ããå¯èœæ§ããããã€ã³ã¹ã¿ã³ã¹ã¡ã³ããŒã§è¡ãããããšãšå®è¡æã®åäœã«äžèŽãã this.prototype
ãä»ããŠã€ã³ã¹ã¿ã³ã¹ã¿ã€ããååŸã§ããŸãã
abstract class Model {
static findAll(): Promise<this.prototype[]>
}
class User extends Model {}
const users: User[] = await User.findAll();
ããã¯ãJavaScriptã§ã®åäœãšäžèŽããŸãã this
ã¯ã¯ã©ã¹ãªããžã§ã¯ãèªäœã§ãããã€ã³ã¹ã¿ã³ã¹ã¯this.prototype
ã«ãããŸãã ããã¯åºæ¬çã«ãããåãšåãã¡ã«ããºã ã§ããã this['prototype']
ã«çžåœããŸãã
åæ§ã«ãéçãªåŽé¢ãthis.constructor
ãä»ããŠã€ã³ã¹ã¿ã³ã¹ã¡ã³ããŒã§å©çšå¯èœã§ãããšæ³åã§ããŸãïŒãã®ATMã®ãŠãŒã¹ã±ãŒã¹ã¯èããããŸããïŒã
ãŸããåè¿°ã®åé¿ç/ããã¯ã®ãããããSequelizeã§ORMã¢ãã«ãå ¥åããããã«æ©èœããªãããšã«ãèšåããããšæããŸãã
this
åã¢ãããŒã·ã§ã³ã¯ã³ã³ã¹ãã©ã¯ã¿ãŒã§ã¯äœ¿çšã§ããªãããããã®ã·ã°ããã£ãŒã§ã¯æ©èœããŸãããts
abstract class Model {
constructor(values: Partial<this.prototype>)
}
ts
abstract class Model {
static attributes: {
[K in keyof this.prototype]: {
type: DataType,
field: string,
unique: boolean,
primaryKey: boolean,
autoIncrement: boolean
}
};
}
ãã®ãªã¯ãšã¹ãã«ã¯+1ã ç§ã®ORMã¯ãšãŠããããã«ãªããŸãã
ããã«ã¯ãªãŒã³ãªãœãªã¥ãŒã·ã§ã³ã衚瀺ãããããšãé¡ã£ãŠããŸã
ãã®éã解決çãæäŸããŠããããã¹ãŠã®äººã«æè¬ããŸãïŒ
ãã以äžã®è°è«ããªãã®ã§ãããã«ã€ããŠããã«é²ãã§ãããã§ããïŒ
ã©ãã«æã£ãŠãããŸããïŒ ããã¯ãç§ãç¥ãéããTypescriptãJavascriptããããã«ã¢ãã«åã§ãããåã«ãããè¡ããªã以å€ã®åé¿çãèŠãããšããªãæ¹æ³ã§ãã
ãã§ã«3人ã®äººæ°ã®ããORMææè ããã®æ©èœãæ±ããŠããã®ãèŠãããšãã§ããã®ã§ãããã¯ORMéçºè ã«ãšã£ãŠå¿ é ã®æ©èœã§ãã
@ pleerock @ xealotãœãªã¥ãŒã·ã§ã³ã¯äžèšã§ææ¡ãããŠããŸãã
export type StaticThis<T> = { new (): T };
export class Base {
static create<T extends Base>(this: StaticThis<T>) {
const that = new this();
return that;
}
baseMethod() { }
}
export class Derived extends Base {
derivedMethod() { }
}
// works
Base.create().baseMethod();
Derived.create().baseMethod();
// works too
Derived.create().derivedMethod();
// does not work (normal)
Base.create().derivedMethod();
ç§ã¯ãããåºã䜿ã£ãŠããŸãã åºæ¬ã¯ã©ã¹ã§ã®éçã¡ãœããã®å®£èšã¯å°ãéãã§ãããéçã¡ãœããå
ã®this
ã®ã¿ã€ãã®æªã¿ãé¿ããããã«æ¯æã代åã§ãã
@pleerock
this:
ãã¿ãŒã³ãåé¡ãªãåºç¯å²ã«äœ¿çšãã瀟å
ORMããããŸãã
確ãã«å°ãè€éã§ãããæ©èœãå®éã«ãã§ã«ããã«ããå Žåã¯ãèšèªãéå é»ããå¿ èŠã¯ãªããšæããŸãã ããæ確ãªæ§æã®ãŠãŒã¹ã±ãŒã¹ã¯ããªãéå®ããããã®ã§ãããççŸãåŒãèµ·ããå¯èœæ§ããããŸãã
ãã¶ãããã®è³ªåãšåç §çšã®ãœãªã¥ãŒã·ã§ã³ãåããStackoverflowã¹ã¬ãããããå¯èœæ§ããããŸããïŒ
@bjouhier @ceymardãã®ã¹ã¬ããã®ãã¹ãŠã®åé¿çãSequelizeã§æ©èœããªãçç±ã説æããŸããïŒ https ïŒ//github.com/Microsoft/TypeScript/issues/5863#issuecomment -269463313
ãããŠãããã¯ORMã ãã§ãªããæšæºã©ã€ãã©ãªã§ããããŸãïŒ https ïŒ//github.com/Microsoft/TypeScript/issues/5863#issuecomment -244550725
@felixfbeckerã³ã³ã¹ãã©ã¯ã¿ãŒã®ãŠãŒã¹ã±ãŒã¹ã«ã€ããŠæçš¿ãããããåé€ããŸããïŒTSã¯ãæçš¿çŽåŸã«ãã¹ãŠã®ãµãã¯ã©ã¹ã§ã³ã³ã¹ãã©ã¯ã¿ãŒã矩åä»ããŠããããã§ã¯ãªãããšã«æ°ä»ããŸããïŒã
@felixbeckerã³ã³ã¹ãã©ã¯ã¿ãŒã®å Žåã«ã€ããŠã¯ããã©ã¡ãŒã¿ãŒã®ãªãã³ã³ã¹ãã©ã¯ã¿ãŒã«åºå·ãã代ããã«ç¹æ®ãªéçã¡ãœããïŒcreateãcloneã...ïŒãæäŸããããšã§è§£æ±ºããŸãã ããæ確ã§å ¥åãç°¡åã§ãã
@bjouhierã€ãŸããåºæ¬çã«ãã¹ãŠã®ã¢ãã«ãµãã¯ã©ã¹ã®ãã¹ãŠã®ã¡ãœãããå宣èšããå¿ èŠããããŸãã Sequelizeã«ããã€ãããèŠãŠãã ããïŒhttpïŒ //docs.sequelizejs.com/class/lib/model.js~Model.html
ç§ã®è°è«ã¯å®å šã«ç°ãªãèŠç¹ããã§ãã éšåçã§ããçŽæçã§ãªãåé¿çããããããããååã§ãããã©ããã«ã€ããŠè°è«ãããæèŠãç°ã«ãããããããšã¯ã§ããŸãããããã¯TypescriptãJavascriptãç°¡åã«ã¢ãã«åã§ããªãé åã§ããããšã«åæã§ããŸãã
ãããŠç§ã®ç解ã§ã¯ãTypescriptã¯Javascriptã®æ¡åŒµã§ããå¿ èŠããããŸãã
@felixfbecker
ã€ãŸããåºæ¬çã«ãã¹ãŠã®ã¢ãã«ãµãã¯ã©ã¹ã®ãã¹ãŠã®ã¡ãœãããå宣èšããå¿ èŠããããŸãã
ã©ãããŠïŒ ããã¯ç§ã®çµéšã§ã¯ãããŸããã ã³ãŒããµã³ãã«ã§åé¡ã説æã§ããŸããïŒ
@bjouhierãã®ã¹ã¬ããã®ã³ã¡ã³ãã®ã³ãŒããµã³ãã«ã䜿çšããŠãåé¡ã詳现ã«èª¬æããŸãããhttpsïŒ //github.com/Microsoft/TypeScript/issues/5863#issuecomment -222348054
ããããäžèšã®create
ã®äŸãèŠãŠãã ããã create
ã¡ãœããã¯éçã¡ãœããã§ãã å宣èšãããŠããŸãããããµãã¯ã©ã¹ã«é©åã«å
¥åãããŠããŸãã ã§ã¯ããªãModel
ã®ã¡ãœãããåå®çŸ©ããå¿
èŠãããã®ã§ããããã
@felixfbeckerããªãã®_æåã®_äŸïŒ
export type StaticThis<T> = { new (): T };
abstract class Model {
public static tableName: string;
public static findById<T extends Model>(this: StaticThis<T>, id: number): T {
const instance = new this();
// details omitted
return instance;
}
}
class User extends Model {
public static tableName = 'users';
public username: string;
}
const user = User.findById(1);
console.log(user.username);
@bjouhierããããŸãããã€ãŸãã this: { new (): T }
ã¢ãããŒã·ã§ã³ã«ãã£ãŠãå®éã«åæšè«ãæ©èœããããã«èŠããŸãã ããã¯ããªããããã³ã³ãã€ã©ãŒã䜿çšããããã©ã«ãã®ã¿ã€ãã§ã¯ãªãã®ãçåã«æããŸãã
ãã¡ãããã³ã³ã¹ãã©ã¯ã¿ãŒã¯this
ãã©ã¡ãŒã¿ãŒãæã€ããšãã§ããªããããåé¿çã¯æ©èœããŸããã
ã¯ããã³ã³ã¹ãã©ã¯ã¿ãŒã§ã¯æ©èœããŸããããéçãªcreate
ã¡ãœãããè¿œå ããããšã§ãAPIãå°ãå€æŽããã ãã§åé¡ãåé¿ã§ããŸãã
ç§ã¯ãããç解ããŠããŸãããããã¯JavaScriptã©ã€ãã©ãªã§ããããã宣èšã«æ¢åã®APIãå ¥åããããšã«ã€ããŠè©±ããŸãã
this
ãéçã¡ãœããå
ã®{ new (): T }
$ãæå³ããå Žåã this
ã¯éçã¡ãœããå
ã®this
ã®æ£ããã¿ã€ãã§ã¯ãããŸããã ããšãã°ã new this()
ã¯èš±å¯ãããŸããã äžè²«æ§ãä¿ã€ããã«ã this
ã¯ãã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ã®åã§ã¯ãªããã³ã³ã¹ãã©ã¯ã¿ãŒé¢æ°ã®åã§ããå¿
èŠããããŸãã
æ¢åã®ã©ã€ãã©ãªã®å
¥åã§åé¡ãçºçããŸãã ãã®ã©ã€ãã©ãªãå¶åŸ¡ã§ããªãå Žåã§ããé©åã«åæå®ãããcreate
é¢æ°ã䜿çšããŠäžéåºæ¬ã¯ã©ã¹ïŒ BaseModel extends Model
ïŒãäœæãã BaseModel
ãããã¹ãŠã®ã¢ãã«ã掟çãããããšãã§ããŸãã
åºæ¬ã¯ã©ã¹ã®éçããããã£ã«ã¢ã¯ã»ã¹ããå Žåã¯ã次ã䜿çšã§ããŸãã
public static findById<T extends Model>(this: (new () => T) & typeof Model, id: number): T {...}
ããããã³ã³ã¹ãã©ã¯ã¿ãŒã«ã€ããŠã¯ããããæå¹ãªãã€ã³ãããããŸãã ã³ã³ãã€ã©ã以äžãæåŠããªããã°ãªããªããšããé£ããçç±ã¯ããããŸããã
constructor(values: Partial<this>) {}
ããã«çã¿ããããšãã@xealotã«åæããŸãã æžããããšãŠããã£ãããã§ã
static findById(id: number): instanceof this { ... }
ãã以å€ã®
static findById<T extends Model>(this: (new () => T), id: number): T { ... }
ããããã¿ã€ãã³ã°ã·ã¹ãã ã«æ°ããæŒç®åãå¿
èŠã§ãïŒ instanceof
ïŒïŒã 以äžã¯ç¡å¹ã§ãã
static findById(id: number): this { ... }
TS 2.4ã¯ããããã®åé¿çãæã¡ç ŽããŸããã
https://travis-ci.org/types/sequelize/builds/247636686
@ sandersn @ felixfbeckerããã¯æå¹ãªãã°ã ãšæããŸãã ããããæå°éã®åçŸã¯ã§ããŸããã ã³ãŒã«ããã¯ãã©ã¡ãŒã¿ã¯åå€ã§ãã
// Hooks
User.afterFind((users: User[], options: FindOptions) => {
console.log('found');
});
ããã¯ãã€ãä¿®æ£ãããå¯èœæ§ããããŸããïŒ
ä»æ¥ãããã«åºããããŸããã åºæ¬çã«ã次ã®ãããªã·ã³ã°ã«ãã³åºæ¬ã¯ã©ã¹ãæ§ç¯ãããã£ãã®ã§ãã
abstract class Singleton<T> {
private static _instance?: T
public static function getInstance (): T {
return this._instance || (this._instance = new T())
}
}
䜿çšæ³ã¯æ¬¡ã®ããã«ãªããŸãã
class Foo extends Singleton<Foo> {
bar () {
console.log('baz!')
}
}
Foo.getInstance().bar() // baz!
ç§ã¯ããã®çŽ10ã®ããªãšãŒã·ã§ã³ãè©ŠããŸããããäžèšã®StaticThis
ã®ããªãšãŒã·ã§ã³ãšä»ã®å€ãã®ããªãšãŒã·ã§ã³ããããŸãã çµå±ãã³ã³ãã€ã«ããã§ããããŒãžã§ã³ã¯1ã€ã ãã§ããã getInstance()
Object
ãšããŠå°åºãããŸããã
ãã®ããã«æ§æãæäœããå¿ èŠããããããã¯ããã«é£ãããšæããŠããŸãã
以äžã®äœåïŒ
class Singleton {
private static _instance?: Singleton;
static getInstance<T extends Singleton>(this: { new(): T }) {
const constr = this as any as typeof Singleton; // hack
return (constr._instance || (constr._instance = new this())) as T;
}
}
class Foo extends Singleton {
foo () { console.log('foo!'); }
}
class Bar extends Singleton {
bar () { console.log('bar!');}
}
Foo.getInstance().foo();
Bar.getInstance().bar();
this as any as typeof Singleton
ã®éšåã¯èŠèŠããã§ããã _instance
ã掟çã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã«æ ŒçŽããå¿
èŠããããããåã·ã¹ãã ãã ãŸããŠããããšã瀺ããŠããŸãã
éåžžãåºæ¬ã¯ã©ã¹ã¯ãã¬ãŒã ã¯ãŒã¯ã«åã蟌ãŸãããããå®è£ ãå°ãéãå Žåã§ãããã»ã©å®³ã¯ãããŸããã éèŠãªã®ã¯ã掟çã¯ã©ã¹ã®ã¯ãªãŒã³ãªã³ãŒãã§ãã
ç§ã¯2.8ãã€ããªãŒã§ã次ã®ãããªããšãã§ããããšãæãã§ããŸããã
static findById(id: number): InstanceType<this> { ... }
æ²ããããšã«ãã®ãããªéã¯ãããŸãã:(
@bjouhierã³ãŒãäŸã¯é åã®ããã«æ©èœããŸãã ãã ããIntelliSenseãªãŒãã³ã³ããªãŒãã解é€ããŠãã ããã
React 16.3.0ããªãªãŒã¹ãããŸããããéçã¡ãœãããã¯ã©ã¹åãã©ã¡ãŒã¿ãŒãåç
§ã§ããªããããæ°ããgetDerivedStateFromProps
ã¡ãœãããæ£ããå
¥åããããšã¯äžå¯èœã®ããã§ãã
ïŒç°¡ç¥åããäŸïŒ
class Component<P, S> {
static getDerivedStateFromProps?<K extends keyof S>(nextProps: P, prevState: S): Pick<S, K> | null
props: P
state: S
}
åé¿çã¯ãããŸããïŒ ïŒãPãšSãPPãšSSãšããŠå ¥åããããšã¯æ°ããŸãããéçºè ããããã2ã€ã®åæãæ£ç¢ºã«äžèŽãããããšãé¡ã£ãŠããŸããïŒpïŒ
PRïŒ https ïŒ//github.com/DefinitelyTyped/DefinitelyTyped/pull/24577
@cncolderç§ãã€ã³ããªã»ã³ã¹ã®ç Žå£ãç®æããŸããã ç§ã¯ãããtypescript2.7ããå§ãŸã£ããšä¿¡ããŠããŸãã
ããã«è¡šç€ºãããŠããªãããšã®1ã€ã¯ãã·ã³ã°ã«ãã³ã®äŸãæ¡åŒµããããšã§ããã·ã³ã°ã«ãã³/ãã«ããã³ã¯ã©ã¹ã«ä¿è·ãããã³ã³ã¹ãã©ã¯ã¿ãŒãæãããã®ãäžè¬çãªãã¿ãŒã³ã§ãããã®ããã«åã{ new(): T }
ã®å Žåããããæ¡åŒµããããšã¯ã§ããŸããããããªãã¯ã³ã³ã¹ãã©ã¯ã¿ãŒã匷å¶ããŸã-ããã§æäŸãããthis
çšèªãŸãã¯ä»ã®ãœãªã¥ãŒã·ã§ã³ïŒ instanceof this
ã typeof this
ãªã©ïŒã¯ããã®åé¡ã解決ããã¯ãã§ãã ããã¯ãã·ã³ã°ã«ãã³ãäœæãªã©ãèŠæ±ããªãã£ãå Žåã«ã³ã³ã¹ãã©ã¯ã¿ãŒã§ãšã©ãŒãã¹ããŒããããšã§ééããªãå¯èœã§ãããããã¯ãšã©ãŒã®å
¥åã®ç®çãç¡å¹ã«ããŸã-ã©ã³ã¿ã€ã ãœãªã¥ãŒã·ã§ã³ãååŸããããã«...
class Singleton {
private static _instance?: Singleton;
public static getInstance<T extends Singleton> ( this: { new(): T } ): T {
const ctor: typeof Singleton = this as any; // hack
return (ctor._instance || (ctor._instance = new this())) as T;
}
protected constructor ( ) { return; }
}
class A extends Singleton {
protected constructor ( ) {
super();
}
}
A.getInstance() // fails because constructor is not public
TSã§getInstance()
ã®ã·ã³ã°ã«ãã³ãå¿
èŠãªçç±ã¯ããããŸããããªããžã§ã¯ããªãã©ã«ãå®çŸ©ããã ãã§ãã ãŸãã¯ã絶察ã«ã¯ã©ã¹ã䜿çšããå ŽåïŒãã©ã€ããŒãã¡ã³ããŒã®å ŽåïŒãã¯ã©ã¹ã§ã¯ãªãã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ã®ã¿ããšã¯ã¹ããŒãããããã¯ã©ã¹åŒïŒ export new class ...
ïŒã䜿çšããŸãã
ããã¯ãã«ããã³ã«ãšã£ãŠãã䟿å©ã§ã-ãããŠç§ã¯ããŸããããã¿ãŒã³ãèŠã€ãããšæããŸã...ããã¯ãã®ã¿ã€ããªãã§ã¯ãŸã éåžžã«ããããŒãªæãã§ãã..代ããã«ããã¯å¿ èŠã§ã
this
-> { new(): T } & typeof Multiton | Function
class Multiton {
private static _instances?: { [key: string]: any };
public static getInstance<T extends Multiton> (
this: { new(): T } & typeof Multiton | Function, key: string
): T {
const instances: { [key: string]: T } =
(this as typeof Multiton)._instances ||
((this as typeof Multiton)._instances = { });
return (instances[key] ||
(instances[key] = new (this as typeof Multiton)() as T)
);
}
protected constructor ( ) { return; }
}
class A extends Multiton {
public getA ( ): void { return; }
}
A.getInstance("some-key").getA();
assert(A.getInstance("some-key") === A.getInstance("some-key"))
new A(); // type error, protected constructor
ããŒãæ ŒçŽããã³ãŒããããã®ã§ãäœææã«åã¯ã©ã¹ã§ã¢ã¯ã»ã¹ã§ããŸãããç°¡åã«ããããã«ãããåé€ããŸãã...
ããã«ã¡ã¯ã ã³ã³ã¹ãã©ã¯ã¿ãŒã«å€æ çãªãthisããå¿ èŠãªåé¡ãçºçããŠããŸãã ãã®ã³ã¡ã³ãã«äŒŒãŠããŸãã
ã¯ã©ã¹ãäœãããã§ãã ã¯ã©ã¹èªäœã«ã¯éåžžã«å€ãã®ããããã£ãããããããã®ã¯ã©ã¹ã®ãã¹ãŠã®ããããã£ãã³ã³ã¹ãã©ã¯ã¿ãŒã®ãã©ã¡ãŒã¿ãŒãä»ããŠåæåãããŠããå Žåãã³ã³ã¹ãã©ã¯ã¿ãŒã¯èŠæ ãããããããŸããã
ç§ã¯ãããããã£ãåæåããããã«ãªããžã§ã¯ããåãå ¥ããã³ã³ã¹ãã©ã¯ã¿ãŒã奜ã¿ãŸãã äŸãã°ïŒ
class Vehicle {
// many properties here
// ...
constructor(value: Partial<Vehicle>) {
Object.assign(this, value)
}
}
let vehicle = new Vehicle({
// <-- IntelliSense works here
})
次ã«ãã¯ã©ã¹ãæ¡åŒµããããšæããŸãã äŸãã°ïŒ
class Car extends Vehicle {
// more properties here
// ...
}
let car = new Car({
// <-- I can't infer Car's properties here
})
this
åãã³ã³ã¹ãã©ã¯ã¿ãŒã§ã䜿çšã§ãããšéåžžã«äŸ¿å©ã§ãã
class Vehicle {
// ...
constructor(value: Partial<this>) {
// ...
ãããã£ãŠãIntelliSenseã¯ãè¿œå ã®å®åæãªãã§åã¯ã©ã¹ã®ããããã£ãæšæž¬ã§ããŸããããšãã°ãã³ã³ã¹ãã©ã¯ã¿ãŒãåå®çŸ©ããŸãã ã¯ã©ã¹ãåæåããããã«éçã¡ãœããã䜿çšãããããèªç¶ã«èŠããŸãã
let car = new Car({
// <-- Car's properties will be able to be inferred if Partial<this> is allowed
})
äœåãããããé¡ãç³ãäžããŸãã
ãã®ã¹ã¬ãããèŠã€ããŠããã£ãã§ãã æ£çŽãªãšãããããã¯éåžžã«æ·±å»ãªåé¡ã§ããã3.0ã«ç§»è¡ããã®ãèŠãã®ã¯éåžžã«èœèãããšæããŸãã
ãã¹ãŠã®è§£æ±ºçãæ€èšããéå»2幎éã«è©ŠããããŸããŸãªåé¿çãæ€èšãããšã解決çãæŽã£ãŠããå Žåãç§ãã¡ãè©Šã¿ãè¿ éãªä¿®æ£ã¯åã«å€±æãããšããçµè«ã«éããŸããã ãããŠãããŸã§ãç§ãã¡ãè¡ããã¹ãŠã®åŒ·å¶ã¯ããããžã§ã¯ãå šäœã§ãããç¶æããããã«ããŸãã«ãå€ãã®æäœæ¥ãå¿ èŠãšããŸãã ãããŠãäžåºŠå ¬éããããšãæ¶è²»è ã«ããªãèªèº«ã®èãæ¹ãç解ããŠãããã圌ããåã«ããªãã®ããã±ãŒãžãããã©ã§æ¶è²»ããããç§ãã¡ã®ã»ãšãã©ã®ããã«VSCodeã§åäœããå ŽåãTypeScriptã§ããäœããä¿®æ£ããããšãéžãã çç±ãç解ããããã«æ±ããããšã¯ã§ããŸããã
åæã«ãå®éã®èšèªãåé¡ã§ã¯ãªããšãã«åã·ã¹ãã ã幞ãã«ããã³ãŒããæžãããšã¯ãããããåæ©èœã䜿çšããã®ãšãŸã£ããåãçç±ã«åããŸãã
ã¿ããªãžã®ç§ã®æšèŠã¯ãæ³¢ç·ãäžå®å
šã§ããããšãåãå
¥ããŠãå¯èœã§ããã°//@ts-ignore because my code works as expected
ã䜿ãããšã§ãã
ããªãã®ãªã³ã¿ãŒãåççãªäººéã®ç¥æ§ã®åœ±é¿ãåããªãå Žåã¯ããã®å Žæãç¥ã£ãŠãããªã³ã¿ãŒãèŠã€ããæãæ¥ãŸããã
æŽæ°ïŒ
éçæšè«ãå€åå®å
šã«æ¡åŒµããããã®ç¬èªã®è©Šã¿ãè¿œå ãããã£ãã®ã§ãã ãã®ã¢ãããŒãã¯ãéªéã«ãªããªãããã«æå³ãããŠãããããå³å¯ã«ã¢ã³ããšã³ãã§ãã ããã¯åŸ¹åºçã«æ瀺çã§ãããç¶æ¿ãããªãã®ããã«ä»äºãããã ãããšåã«ä»®å®ããã®ã§ã¯ãªããããªãã«ããªãã®å¢åŒ·ããã§ãã¯ããããšã匷å¶ããŸãã
export class Sequence<T> {
static from(...values) {
// ⊠returns Sequence<T>
};
}
export class Peekable<T> extends Sequence<T> {
// no augmentations needed in actual class body
}
/// AMBIENT /// Usually keep those at the bottom of my files
export declare namespace Peekable {
export function from<T>(... values: T[]): Peekable<T>;
}
æããã«ããã®ãã¿ãŒã³ãæãç«ã€ããšãããã®ã¹ã¬ããã®ãã¹ãŠã®ã·ããªãªãæºããããšãä¿èšŒããããšã¯ã§ããŸããããä»ã®ãšãããæåŸ ã©ããã«æ©èœããŸãã
ãããã®éžæã¯ããã®æç¹ãŸã§ãTypeScriptèªäœã®libãã¡ã€ã«ã«ã¯2ã€ã®ã¯ã©ã¹å®£èšããå«ãŸããŠããªããšããæžå¿µããçããŠããŸãã
/**
* Represents an Automation SAFEARRAY
*/
declare class SafeArray<T = any> {
private constructor();
private SafeArray_typekey: SafeArray<T>;
}
/**
* Automation date (VT_DATE)
*/
declare class VarDate {
private constructor();
private VarDate_typekey: VarDate;
}
ä»æ¥ã¯ãã°ããè°è«ããŸããã ããŒãã€ã³ãïŒ
this
ã¯ã€ã³ã¹ã¿ã³ã¹åŽãŸãã¯éçåŽãæããŸããïŒInstanceTypeOf
ãä»ããŠåç
§ã§ããŸããããã®éã¯åœãŠã¯ãŸããŸããã ããã«ããã眲åã®this
ãæ¬æã®this
ãšåãã¿ã€ãã«ãªããšãã察称æ§ãç¶æãããŸããstatic
ã¡ãœããã§ã®new this()
ã®äžå¥å
šãªåŒã³åºãã¯ãã§ã«èš±å¯ãããŠããŸãthis
ã®æ§æ眲ååŽãå€éšããæ°ã«ãã人ã¯ããªãã§ãããããæ¢åã®åé¿çïŒ
class Foo {
static boo<T extends typeof Foo>(this: T): InstanceType<T> {
return (new this()) as InstanceType<T>;
}
}
class Bar extends Foo {
}
// b: Bar
let b = Bar.boo();
ç¹ã«ãããã¯Bar
ã®æ§æ眲åãFoo
ã®ä»£ããã«é©åã«äœ¿çšã§ããå Žåã«ã®ã¿æ©èœããŸãã
@RyanCavanaughç§ã¯this
ã®å€ãããªãã®äŸstatic boo<T extends typeof Foo>(this: T): InstanceType<T>
ããæ¥ãŠãããšãã説æãèãåºãããšããŠããŸããããç§ã¯ãããç解ããŠããŸããã 確ãã«ç§ã¯ãžã§ããªãã¯å»è¬åã®ãã¹ãŠãèªã¿çŽããŸããããããã§ã-ãããã ããšãã°ã this
ãclazz
ã«çœ®ãæãããšãããã¯æ©èœããªããªããã³ã³ãã€ã©ã¯ã1ã€ã®åŒæ°ãå¿
èŠã§ããã0ãååŸããŸããããšæå¥ãèšããŸãã ã ãããããã€ãã®éæ³ãããã§èµ·ãã£ãŠããŸãã 説æããŠããããŸããïŒ ãŸãã¯ãããã¥ã¡ã³ãã®æ£ããæ¹åã瀺ããŠãã ããã
ç·šéïŒ
ãŸãããªãããã¯åã«extends Foo
ã§ã¯ãªã$ïŒ extends typeof Foo
$ïŒ$ãªã®ã§ããïŒ
@creynders this
ã¯ãé¢æ°ã®ã³ã³ããã¹ãã«åãããŠå
¥åã§ããç¹å¥ãªåœã®ãã©ã¡ãŒã¿ãŒã§ãã ããã¥ã¡ã³ãã
ãžã§ããªãã¯ã¹ãé¢ä¿ããŠããå Žåã InstanceType<T>
ã®äœ¿çšã¯æ©èœããŸããã
ç§ã®ãŠãŒã¹ã±ãŒã¹ã¯æ¬¡ã®ããã«ãªããŸãã
const _data = Symbol('data');
class ModelBase<T> {
[_data]: Readonly<T>;
protected constructor(data: T) {
this[_data] = Object.freeze(data);
}
static create<T, V extends typeof ModelBase>(this: V, data : T): InstanceType<V> {
return new this(data);
}
}
interface IUserData {
id: number;
}
class User extends ModelBase<IUserData> {}
User.create({ id: 5 });
@mastermattãããããããããã¥ã¡ã³ããèªãã§ãããšãã«å®å šã«ãããæŸããŸããã§ãã...ããããšã
@RyanCavanaughã®äŸãèŠããšãéçã¡ãœãããæ©èœãããããšãã§ããŸããããéçã¡ãœãããåç §ããã€ã³ã¹ã¿ã³ã¹ã¡ãœããããããŸããããã®ããã®æ£ããå ¥åæ¹æ³ãç解ã§ããŸããã
äŸïŒ
class Foo {
static boo<T extends typeof Foo>(this: T): InstanceType<T> {
return (new this()) as InstanceType<T>;
}
boo<T extends typeof Foo>(this: InstanceType<T>): InstanceType<T> {
return (this.constructor as T).boo();
}
}
class Bar extends Foo {
}
// b: Bar
let b = Bar.boo();
// c: Foo
let c = b.boo();
ãã®æåŸã®åé¡ã®åé¿çãèŠã€ããããšãã§ããã°ãäœãå ¬åŒãªããšãæ¥ããŸã§ç§ã¯èšå®ãããŸãã
ãŸãããã®äŸã§ã¯ããµãã¯ã©ã¹ãéçã¡ãœããããªãŒããŒã©ã€ãããŠsuper
ãåŒã³åºãããšãããšããã¹ãŠãæ··ä¹±ããŸã...ããã2ã€ã®åé¡ãé€ãã°ãåé¿çã¯åé¡ãªãæ©èœããŠããããã§ãã ãã ããããã2ã€ã®åé¡ã¯ãã³ãŒããããªããããã¯ããŠããŸãã
IIRCããã¯ãåã·ã¹ãã ãå°ãæ²ããªããšã¿ã€ãã¹ã¯ãªããã§è¡šçŸã§ããªãããã§ãã ã®ããã«; this.constructorã¯ãããªããæã£ãŠãããã®ããŸãã¯ãã®ãããªãã®ã§ãããšã¯ãŸã£ããä¿èšŒãããŠããŸããã
ãã®æ£ç¢ºãªã±ãŒã¹ã§ã¯ã boo()
ã€ã³ã¹ã¿ã³ã¹ã¡ãœãããthis
ãè¿ããå
éšã§å°ãããŒãããŠãã³ã³ãã€ã©ã«èªåãäœãããŠããããç¥ã£ãŠããããšãåãå
¥ããããŸãã
ç§ã®äžè¬çãªçç±ã¯ãAPIãã³ãŒãã®æ®ãã®éšåã§ã§ããã ãåçŽã«ããããšããããšã§ããããšãããããå°ãäžæ£è¡çºãæå³ããå Žåã§ãã
誰ãããã£ãšé 匷ãªãã®ãæã£ãŠãããªããç§ã¯ããã倧奜ãã§ã
class Foo {
static boo<T extends typeof Foo>(this: T): InstanceType<T> {
return (new this()) as InstanceType<T>;
}
boo(): this {
// @ts-ignore : wow this is ugly
return (this.constructor).boo();
}
}
class Bar extends Foo {
}
// b: Bar
let b = Bar.boo();
// c: Bar !
let c = b.boo();
ã€ã³ã¿ãŒãã§ã€ã¹ã«ãŒãã«ç§»åããŠããã®ãããªããšãè¡ãããšãã§ããŸã;
interface FooMaker<T> {
new(...a: any[]): T
boo(): T
}
class Foo {
static boo<T extends typeof Foo>(this: T): InstanceType<T> {
return (new this()) as InstanceType<T>;
}
boo(): this {
return (this.constructor as FooMaker<this>).boo();
}
}
class Bar extends Foo {
}
// b: Bar
let b = Bar.boo();
// c: Bar !
let c = b.boo();
ãããäžæ£è¡çºã§ãããããå°ãå¶åŸ¡ãããŠããã®ã§ã¯ãªãã§ããããã æ¬åœã«èšããŸããã
ãããã£ãŠãéçãªãbooãã¡ãœããã®æåã®this
åŒæ°ã¯ãéåžžã®åŒæ°ãšããŠã§ã¯ãªããç¹å¥ã«æ±ãããŸããïŒ ããã説æããããã¥ã¡ã³ããžã®ãªã³ã¯ã¯ãããŸããïŒ
class Foo { static boo<T extends typeof Foo>(this: T): InstanceType<T> { return (new this()) as InstanceType<T>; } } class Bar extends Foo { } // b: Bar let b = Bar.boo();
ç§ã¯åãïŒå°ãªããšãåæ§ã®ïŒåé¡ãæ±ããŠããŸãã
ç§ã¯JSDocïŒTypeScriptã§ã¯ãªãïŒã§Vanilla Javascriptã䜿çšããŠããããããã®ã¹ã¬ããã§ææ¡ãããŠãããžã§ããªãã¯ãäžå¿ãšããåé¿çã䜿çš/å®è£
ããããšã¯ã§ããŸããããã«ãŒãã¯åãããã§ãã
ç§ã¯ãã®åé¡ãéããŸããïŒïŒ28880
ãã®åé¡ã¯æåéããã§ã«3幎ã«ãªããŸãã
誰ããç§ã®ããã«åãããšãã§ããé©åãªåé¿çãèŠã€ããŸãããïŒ
3幎
@RyanCavanaughã®åé¿çã¯éçã¡ãœããã«ã¯æé©ã§ãããéçã¢ã¯ã»ãµãŒã¯ã©ãã§ããããã
class Factory<T> {
get(): T { ... }
}
class Base {
static factory<T extends Base>(this: Constructor<T>): Factory<T> {
//
}
// what about a getter?
static get factory<** no generics allowed for accessors **> ...
}
3幎
ããŠãããªãã¯æ¥ä»ãåŒãã®ã«ååãŸãšãã§ãã ããããããªãã¯è§£æ±ºçãæäŸã§ããŸããïŒ ;ïŒ
@RyanCavanaughããã¯ããžã§ãã¬ãŒã¿ãŒã§æ¬¡ã®ããã«this
å€ã䜿çšããå Žåã®åé¡ã§ãã
class C {
constructor(f: (this: this) => void) {
}
}
new C(function* () {
this;
yield;
});
ãžã§ãã¬ãŒã¿ãŒãäœæããå Žåãç¢å°é¢æ°ã䜿çšããŠthis
å€ã䜿çšããããšã¯ã§ããŸããã ãããã£ãŠããµãã¯ã©ã¹ã§this
åãæ瀺çã«å®£èšããå¿
èŠããããŸãã å®éã®ã±ãŒã¹ã¯æ¬¡ã®ãšããã§ãã
class Component extends Coroutine<void> implements El {
constructor() {
super(function* (this: Component) {
while (true) {
yield;
}
}, { size: Infinity });
}
private readonly dom = Shadow.section({
style: HTML.style(`ul { width: 100px; }`),
content: HTML.ul([
HTML.li(`item`)
] as const),
});
public readonly element = this.dom.element;
public get children() {
return this.dom.children.content.children;
}
public set children(children) {
this.dom.children.content.children = children;
}
}
https://github.com/falsandtru/typed-dom/blob/v0.0.134/test/integration/package.ts#L469
åºæ¬ã¯ã©ã¹ã§å®£èšã§ããå Žåã¯ããµãã¯ã©ã¹ã§this
åã宣èšããå¿
èŠã¯ãããŸããã ãã ãããžã§ãã¬ãŒã¿ãã¹ãŒããŒã¯ã©ã¹ã§åæçã«åŒã³åºãããå Žåã this
å€ã¯åæåãããŸããã ç§ã¯ã³ãŒãã§ãã®åé¡ãåé¿ããŸããããããã¯æ±ãããã¯ã§ãã ãããã£ãŠããã®ãã¿ãŒã³ã¯å
ã
ãã¯ã©ã¹ããŒã¹ã®ããã°ã©ãã³ã°èšèªãšäžèŽããªãå¯èœæ§ããããŸãã
æãã¯ãªãŒã³ã§ã¯ãããŸããããéçã¡ãœããããåã¯ã©ã¹ã«ã¢ã¯ã»ã¹ããã®ã«åœ¹ç«ã€å ŽåããããŸãã
class Base {
static foo<T extends typeof Base>() {
let ctr = Object.create(this.prototype as InstanceType<T>).constructor;
// ...
}
}
class C extends Base {
}
C.foo();
ç§ãçŸåšçŽé¢ããŠããåé¡ãããã«ãããã®ãã©ããã¯ããããŸãããããã®åé¡ãäžç®èŠãã ãã§ãããããããã ãšæãããŸãã ããã§ãªãå Žåã¯ä¿®æ£ããŠãã ããã
ãããã£ãŠãç¶æ¿ãä»ããŠé¢é£ãã次ã®2ã€ã®ã¯ã©ã¹ããããŸãã
export class Target {
public static create<T extends Target = Target>(that: Partial<T>): T {
const obj: T = Object.create(this.prototype);
this.mapObject(obj, that);
return obj;
}
public static mapObject<T extends Target = Target>(obj: T, that: Partial<T>) {
// works with "strictNullChecks": false
obj.prop1 = that.prop1;
obj.prop2 = that.prop2;
}
public prop1!: string;
constructor(public prop2: string) {}
}
export class SubTarget extends Target {
public subProp!: string;
}
次ã«ã次ã®ããã«SubTarget
ã¯ã©ã¹ã«mapObject
ã¡ãœãããè¿œå ããŸãã
public static mapObject(obj: SubTarget, that: Partial<SubTarget>) {
super.mapObject(obj, that);
obj.subProp = that.subProp;
}
ãããæ©èœããããšãæåŸ ããŠããŸãããã次ã®ãšã©ãŒãçºçããŸãã
Class static side 'typeof SubTarget' incorrectly extends base class static side 'typeof Target'.
Types of property 'mapObject' are incompatible.
Type '(obj: SubTarget, that: Partial<SubTarget>) => void' is not assignable to type '<T extends Target>(obj: T, that: Partial<T>) => void'.
Types of parameters 'obj' and 'obj' are incompatible.
Type 'T' is not assignable to type 'SubTarget'.
Property 'subProp' is missing in type 'Target' but required in type 'SubTarget'.
ãã®åé¡ãåå ã§ãã®ãšã©ãŒãçºçããŸãããïŒ ããã§ãªããã°ã説æã¯æ¬åœã«çŽ æŽãããã§ãããã
åŒã³åºãããå®éã®ã¯ã©ã¹ã®æ°ããã€ã³ã¹ã¿ã³ã¹ãè¿ãéçã¡ãœããã«æ³šéãä»ããããã®è§£æ±ºçãæ¢ããŠãããšãã«ããã«æ¥ãŸããã
@SMotaalã«ãã£ãŠææ¡ãããåé¿çïŒ new this()
ãšçµã¿åãããŠïŒãæãã¯ãªãŒã³ã§ãç§ã«ãšã£ãŠæãçã«ããªã£ãŠãããšæããŸãã ããã«ãããç®çã®ã€ã³ãã³ããè¡šçŸã§ãããžã§ããªãã¯ã¡ãœãããåŒã³åºããã³ã«ã¿ã€ããæå®ããå¿
èŠããªããªããæçµçãªã³ãŒãã«ãªãŒããŒããããè¿œå ãããããšããããŸããã
ããããçå£ã«ãããã¯ãŸã ã³ã¢Typescriptã®äžéšã§ã¯ãªãã®ã§ããïŒ ããã¯ããªãäžè¬çãªã·ããªãªã§ãã
@danielvy â OOPãšãããã¿ã€ãã®éã®æ絶ã¯ã誰ãã幞ãã«ãªããªã倧ããªç²Ÿç¥çã®ã£ããã ãšæããŸãã ä»æ§ã§ã¯ã©ã¹æ©èœãé²åããåã«äœãããã¯ã©ã¹ã«é¢ããäž»èŠãªä»®å®ã¯äžèŽããŠããªãã£ããšæããŸããããããæãåºãããšã¯ãå€ãã®æ©èœããTypeScriptæ©èœã®èœãšãç©Žã§ããããã誰ãããåªå ãããŸããç§ã®èŠè§£ã§ã¯ãã¿ã€ããã 競äºãããåªãã解決çããªãããšã¯ã競äºãããå Žåã«ã®ã¿åé¡ã«ãªããŸãããããã1ã€ã®ãã¹ã±ããã«ãããã¹ãŠã®åµãåžžã«ãã¹ãŠã®äººã«ãšã£ãŠæªãçç±ã§ããç§ã¯ããã§å®çšçã§èª å®ã§ãã
ããã¯æ©èœããŸããïŒ
export class Base {
static getEntitySchema<T extends typeof Base>(
this: T,
): InstanceType<T> {
}
}
export class Extension extends Base {
static member: string = '';
static getEntitySchema<T extends typeof Extension>(
this: T,
): InstanceType<T> {
}
}
Type 'typeof Base' is missing the following properties from type 'typeof Extension ': member.
ããããExtensionã¯Baseãæ¡åŒµããã®ã§ãããã¯èš±å¯ãããã¹ãã§ã¯ãããŸãããïŒ
ãããæ©èœããããšã«æ³šæããŠãã ããã
export class Extension extends Base {
static member: string = '';
static getEntitySchema<T extends typeof Base>(
this: T,
): InstanceType<T> {
}
}
ãã ãããã®äžã§this.memberã䜿çšããããšã¯ã§ããŸããã
ãããã£ãŠã @ ntuckerã®æçš¿ãããæ¡åŒµã¯ã©ã¹ãåºæ¬ã¯ã©ã¹ãšæ£ç¢ºã«äžèŽããªãéããåé¿çã¯1ã¬ãã«ã®æ·±ãã§ããæ©èœããªããšæšæž¬ããŠããŸããïŒ
ããã«ã¡ã¯ïŒ ä¿è·ãããã³ã³ã¹ãã©ã¯ã¿ãŒã¯ã©ãã§ããïŒ
class A {
static create<T extends A>(
this: {new(): T}
) {
return new this();
}
protected constructor() {}
}
class B extends A {}
B.create(); // Error ts(2684)
ã³ã³ã¹ãã©ã¯ã¿ãŒããããªãã¯ã®å Žå-åé¡ãããŸããããããã§ãªãå Žåã¯ãšã©ãŒãçºçããŸãã
The 'this' context of type 'typeof B' is not assignable to method's 'this' of type '(new () => B) & typeof A'.
Type 'typeof B' is not assignable to type 'new () => B'.
Cannot assign a 'protected' constructor type to a 'public' constructor type.
éã³å Ž-httpïŒ//tiny.cc/r74c9y
ããã«åžæã¯ãããŸããïŒ ããäžåºŠãã®å¿ èŠæ§ã«åºããããŸããïŒF
@ntucker Duuuuudeeããã£ã!!! ç§ã«ãšã£ãŠéèŠãªèªèã¯ãéçcreateã¡ãœããããžã§ããªãã¯ã«ãã this
ãã©ã¡ãŒã¿ãŒã宣èšããæåŸã«InstanceType<U>
ãã£ã¹ããå®è¡ããããšã§ããã
äžãã^
class Base<T> {
public static create<U extends typeof Base>(
this: U
) {
return new this() as InstanceType<U>
}
}
class Derived extends Base<Derived> {}
const d: Derived = Derived.create() // works ð
ããã¯ç§ã®ãŠãŒã¹ã±ãŒã¹ãå®å
šã«æºãããTS 3.5.1ã®æç¹ã§ãããã¯ãã®ã¹ã¬ããã®pplã®å€§éšåãæºãããŠããããã§ãïŒéçããããtheAnswer
ãšç¬¬3ã¬ãã«ã®æ¡åŒµã®æ¢çŽ¢ã«ã€ããŠã¯éã³å Žãåç
§ããŠãã ããïŒ
ããããã€ã¯ïŒããã¯çŸåšæ©èœããŠãããéããããšãã§ãããšæããŸããïŒ
@jonjaquesãšããã§ãTã䜿çšããããšã¯ãããŸããããŸããããã¯ãã¡ãœããããªãŒããŒã©ã€ããããšãããç§ãæŠèª¬ããåé¡ã解決ããŸããã
äžèšã®è§£æ±ºçã¯ãã»ãŒ4幎åã«ãã§ã«ææ¡ãããŠããããã«æããŸãããããã§ãåé¡ã解決ãããã®ã§ã¯ãããŸããã
ç§ã¯ã¹ã¿ãã¯ãªãŒããŒãããŒãéããŠã誰ããç¥ã£ãŠãããããããªãä»ã®åé¿çãããã誰ããç§ãçµéšããŠããåé¡ã®è¯ãèŠçŽãæã£ãŠãããã©ããã確èªããŸããïŒ
ããã®ãã©ã¡ãŒã¿ãŒãå«ããã¡ãœãããã©ã¡ãŒã¿ãŒãšããŠäœ¿çšããããžã§ããªãã¯ã¹ã¯åå€ã®ããã«èŠããŸãããå®éã«ã¯ããã®ãã©ã¡ãŒã¿ãŒãåžžã«å ±å€ïŒãŸãã¯å€åäºå€ïŒãšããŠæ±ãå¿ èŠããããŸããã
ãããã£ãŠãããã¯å®éã«ã¯TypeScriptèªäœã§å£ããŠãããã®ã§ãããä¿®æ£ããå¿ èŠãããããã§ãïŒããããã¯å ±å€ãŸãã¯äºå€ã§ããå¿ èŠããããŸãïŒã
ç·šéïŒãã®ã³ã¡ã³ãã«ã¯ãã£ãšè¯ãæ¹æ³ããããŸãã
è¿œå ãããã®ã¯ããŸããããŸãããã httpsïŒ //github.com/microsoft/TypeScript/issues/5863#issuecomment-437217433ããããŸããããŸããã
class Foo {
static create<T extends typeof Foo>(this: T): InstanceType<T> {
return (new this()) as InstanceType<T>;
}
}
class Bar extends Foo { }
// typeof b is Bar.
const b = Bar.create()
ãããããã®é·ãåé¡ãé²èŠ§ããããªã人ã«åœ¹ç«ã€ããšãé¡ã£ãŠããŸãã
å¥ã®ãŠãŒã¹ã±ãŒã¹ã¯ãéã¯ã©ã¹ã®ã«ã¹ã¿ã åã¬ãŒãã¡ã³ããŒé¢æ°ã§ãã
type Baz = {
type: "baz"
}
type Bar = {
type: "bar"
}
type Foo = (Baz|Bar)&{
isBar: () => this is Bar
}
åé¿çã¯ãç§ãå¿ èŠãªå Žæã«ã»ãšãã©å°éããŸãããã®ã¢ãæå ¥ããããã®ã¬ã³ãããã1ã€ãããŸãã 次ã®äžèªç¶ãªäŸãèŠãŠãã ããã
interface IAutomobileOptions {
make: string
}
interface ITruckOptions extends IAutomobileOptions {
bedLength: number
}
export class Automobile<O extends IAutomobileOptions> {
constructor(public options: O) {}
static create<T extends typeof Automobile, O extends IAutomobileOptions>(
this: T,
options: O
): InstanceType<T> {
return new this(options) as InstanceType<T>
}
}
export class Truck<O extends ITruckOptions> extends Automobile<O> {
constructor(truckOptions: O) {
super(truckOptions)
}
}
const car = Automobile.create({ make: 'Audi' })
const truck = Truck.create({ make: 'Ford', bedLength: 7 }) // TS Error on Truck
ãšã©ãŒã¯æ¬¡ã®ãšããã§ãã
The 'this' context of type 'typeof Truck' is not assignable to method's 'this' of type 'typeof Automobile'.
Types of parameters 'truckOptions' and 'options' are incompatible.
Type 'O' is not assignable to type 'ITruckOptions'.
Property 'bedLength' is missing in type 'IAutomobileOptions' but required in type 'ITruckOptions'.ts(2684)
Automobile
ã¯ã©ã¹ã®create
ã¡ãœããã«ã¯$ ITruckOptions
ããO
ãŸã§ã®åç
§ããªããããããã¯ç§ã«ã¯çã«ããªã£ãŠããŸããããã®åé¡ã®åé¿çã¯ïŒ
éåžžãã³ã³ã¹ãã©ã¯ã¿ãŒã®æ¡åŒµã¯ã©ã¹ã®ãªãã·ã§ã³ã¯åºæ¬ã¯ã©ã¹ã®ãªãã·ã§ã³ã€ã³ã¿ãŒãã§ã€ã¹ãæ¡åŒµãããããåºæ¬ã¯ã©ã¹ã®ãã©ã¡ãŒã¿ãŒãåžžã«å«ãŸããããšã¯ããã£ãŠããŸãããæ¡åŒµã®ãã©ã¡ãŒã¿ãŒãå«ãŸããŠããããšã確èªããä¿¡é Œã§ããæ¹æ³ããããŸãããã¯ã©ã¹ã
ãŸããã¯ã©ã¹ãæ¡åŒµããéã«ã¡ãœããããªãŒããŒã©ã€ãããŠãç¶æ¿ããã¯ã©ã¹ã®äºæ³ãããå ¥ååãšæ»ãåãéç¥ããå¿ èŠããããŸããã
@ Jack-Barryããã¯æ©èœããŸãïŒ
interface IAutomobileOptions {
make: string
}
interface ITruckOptions extends IAutomobileOptions {
bedLength: number
}
export class Automobile<O extends IAutomobileOptions> {
constructor(public options: O) { }
static create<T extends Automobile<O>, O extends IAutomobileOptions>(
this: { new(options: O): T; },
options: O
): T {
return new this(options)
}
}
export class Truck<O extends ITruckOptions> extends Automobile<O> {
constructor(truckOptions: O) {
super(truckOptions)
}
}
const car = Automobile.create({ make: 'Audi' });
const truck = Truck.create({ make: 'Ford', bedLength: 7 });
ãã ããã³ã³ã¹ãã©ã¯ã¿ãŒã¯å
¬éãããŠããããããŸã çæ³çã§ã¯ãããŸããããã®ããã new Automobile({ make: "Audi" })
ãå®è¡ããã ãã§æžã¿ãŸãã
@elderapoããã§ç§ã¯å¿ èŠãªãã®ãæã«å ¥ããããšãã§ãããšæããŸã-äŸã¯ãã¡ããèæ¡ãããŠããŸããã_Generics_ã®ç解ã®æ¬ åŠãç§ãå°ãåã¿ããããšãããããããŸãã çä»ããŠãããŠããããšãïŒ
ãããä»ã®äººã®åœ¹ã«ç«ã€ããšãé¡ã£ãŠããŸããæ¹åã®äœå°ããããã©ããæããŠãã ããã èªã¿åãé¢æ°ãã¿ã€ãã³ã°ãšåæããªããªãå¯èœæ§ããããããå®å šã§ã¯ãããŸããããå¿ èŠãªãã¿ãŒã³ã«æãè¿ããã®ã§ãã
// Interface to ensure attributes that exist on all descendants
interface IBaseClassAttributes {
foo: string
}
// Type to provide inferred instance of class
type ThisClass<
Attributes extends IBaseClassAttributes,
InstanceType extends BaseClass<Attributes>
> = {
new (attributes: Attributes): InstanceType
}
// Constructor uses generic A to assign attributes on instances
class BaseClass<A extends IBaseClassAttributes = IBaseClassAttributes> {
constructor(public attributes: A) {}
// this returns an instance of type ThisClass
public static create<A extends IBaseClassAttributes, T extends BaseClass<A>>(
this: ThisClass<A, T>,
attributes: A
): T {
// Perform db creation actions here
return new this(attributes)
}
// Note that read function is a place where typechecking could fail you if db
// return value does not match
public static read<A extends IBaseClassAttributes>(id: string): A | null {
// Perform db retrieval here assign to variable
const dbReturnValue = {} as A | null
return dbReturnValue
}
}
interface IExtendingClassAttributes extends IBaseClassAttributes {
bar: number
}
// Extend the BaseClass with the extending attributes interface
class ExtendingClass extends BaseClass<IExtendingClassAttributes> {}
// BaseClass
const bc: BaseClass = BaseClass.create({ foo: '' })
const bca: IBaseClassAttributes = BaseClass.read('a') as IBaseClassAttributes
console.log(bc.attributes.foo)
console.log(bca.foo)
// ExtendingClass
// Note that the create and read methods do not have to be overriden,
// but typechecking still works as expected here
const ec: ExtendingClass = ExtendingClass.create({ foo: 'bar', bar: 0 })
const eca: IExtendingClassAttributes = ExtendingClass.read(
'a'
) as IExtendingClassAttributes
console.log(ec.attributes.foo)
console.log(ec.attributes.bar)
console.log(eca.foo)
console.log(eca.bar)
ãã®ãã¿ãŒã³ãæ®ãã®CRUDã¢ã¯ã·ã§ã³ã«ç°¡åã«æ¡åŒµã§ããŸãã
@ Jack-Barryã®äŸã§ã¯ãã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãè¿ãããã«read
é¢æ°ãååŸããããšããŠããŸãã ç§ã¯ä»¥äžãæ©èœããããšãæåŸ
ããŠããŸããïŒ
class BaseClass<A extends IBaseClassAttributes = IBaseClassAttributes> {
public static read<A extends IBaseClassAttributes, T extends BaseClass<A>>(
this: ThisClass<A, T>,
id: string,
): T | null {
// Perform db retrieval here assign to variable
const dbReturnValue = {} as A | null
if (dbReturnValue === null) {
return null;
}
return this.create(dbReturnValue);
}
}
ãããã代ããã«ãšã©ãŒProperty 'create' does not exist on type 'ThisClass<A, T>'.
ãååŸããŸããããã«åãçµãæ¹æ³ã«ã€ããŠèª°ããåé¿çãæã£ãŠããŸããïŒ
@everhardt create
ã¡ãœããã¯static
ã§ãããããã€ã³ã¹ã¿ã³ã¹ã§ã¯ãªãã this
ã®class
ã§åŒã³åºãå¿
èŠããããŸãã ãšã¯ããã class
é¢æ°ã«åçã«ã¢ã¯ã»ã¹ããŠãç®çã®åãã§ãã¯ãæäŸããæ¹æ³ã«ã€ããŠã¯ãé ã®ãŠã£ãºãããããŸãåé¿çããããŸããã
ç§ãå
¥æã§ããæãè¿ããã®ã¯ç¹ã«ãšã¬ã¬ã³ãã§ã¯ãªãã BaseClass.create
type
ã䜿çšã§ããªããããç°¡åã«åæãå€ããå¯èœæ§ããããŸãã
return (this.constructor as unknown as { create: (attributes: A) => T }).create(dbReturnValue)
ç§ã¯ããã_ãã¹ãããŠããŸãã_ã
@ Jack-Barryãããšã this.constructor.create is not a function
ãååŸããŸãã
ããã¯çã«ããªã£ãŠããŸããTypescriptã¯this
ãã€ã³ã¹ã¿ã³ã¹ãšããŠè§£éããŠããŸãããæçµçãªjavascriptããŒãµãŒã®å Žåãé¢æ°ã¯éçã§ããããã this
ãã¯ã©ã¹ã§ãã
Jack-Barryã®äŸã®æãã€ã³ã¹ãã¬ãŒã·ã§ã³ãåŸãæ¡åŒµã§ã¯ãªããããããŸãããããã®Playground Linkã§ãç§ãã©ã®ããã«è§£æ±ºãããã確èªã§ããŸãã
æ žå¿ïŒ
ThisClass
ã¯ãBaseClassã®ã¡ãœããïŒéçããã³ã€ã³ã¹ã¿ã³ã¹ã®äž¡æ¹ïŒãããªã¢ãŒãã£ã㯠'this'ã§äœ¿çšãããã¹ãŠã®éçããããã£ãšã¡ãœãããèšè¿°ããå¿
èŠããããŸãã(this.constructor as ThisClass<A, this>)
ã䜿çšããŸãã¯ã©ã¹ãšThisClass
åã®äž¡æ¹ã§éçã¡ãœãããšããããã£ã®åãå®çŸ©ããå¿
èŠããããããããã¯äºéã®äœæ¥ã§ãããç§ã«ãšã£ãŠã¯æ©èœããŸãã
ç·šéïŒéã³å Žã®ãªã³ã¯ãä¿®æ£
PHPã¯ãã£ãšåã«ãã®åé¡ãä¿®æ£ããŸããã èªå·±ã éçã ããã
ã¿ãªããã2020幎ã§ãã_this_ã®åé¡ããããŸãã ð
class Animal {
static create() {
return new this()
}
}
class Bunny extends Animal {}
const bugs = Bunny.create() // const bugs: Animal
bugs
ãBunny
ã®ã€ã³ã¹ã¿ã³ã¹ã«ãªããšæããŸãã
çŸåšã®åé¿çã¯äœã§ããïŒ ç§ã¯ãã®åé¡ã®ãã¹ãŠãè©ŠããŸããããäœãä¿®æ£ãããŠããªãããã§ãã
æŽæ°ïŒããã¯æ©èœããŸãããã this
åŒæ°ã®å®çŸ©ããããŸããã§ããã
class Animal {
static create<T extends typeof Animal>(this: T): InstanceType<T> {
return (new this()) as InstanceType<T>
}
}
class Bunny extends Animal {}
const bugs = Bunny.create() // const bugs: Bunny
ããã«é¢ããåé¡ã¯ãã²ãã¿ãŒãšã»ãã¿ãŒãåãã©ã¡ãŒã¿ãŒãæã€ããšãã§ããªããšããããšã§ãã
ãŸããåé·ãããŸãã
ç§ã¯åæ§ã®åé¡ãæ±ã£ãŠããŸãã ãå€æ çãªå éšã¯ã©ã¹ããå®è£ ããããã«ãç§ãèŠã€ããããšãã§ããæè¯ã®ãã®ã¯æ¬¡ã®ãšããã§ãã
class BaseClass {
static InnerClass = class BaseInnerClass {};
static createInnerClass<T extends typeof BaseClass>(this: T) {
return new this.InnerClass() as InstanceType<T['InnerClass']>;
}
}
class SubClass extends BaseClass {
static InnerClass = class SubInnerClass extends BaseClass.InnerClass {};
}
const baseInnerClass = BaseClass.createInnerClass(); // => BaseInnerClass
const subInnerClass = SubClass.createInnerClass(); // => SubInnerClass
ããŸãæ©èœããŠããããã«èŠããŸããã createInnerClass()
ã®å
¥åã¯ç§ã®æèŠã§ã¯åé·ãããŠãã³ãŒãããŒã¹ã«ãããããããŸãã ãã®ã³ãŒããåçŽåããæ¹æ³ã«ã€ããŠèª°ããäœãã¢ã€ãã¢ãæã£ãŠããŸããïŒ
ãã®ã¢ãããŒãã®åé¡ã¯ãéçãªã²ãã¿ãŒãšã»ãã¿ãŒã§ã¯æ©èœããªãããšã§ãã
éçããããã£ã«self.
ãå®è£
ããã®ã¯ã©ãã§ããïŒ ç§ã¯4幎åã«ãã®åé¡ãæ±ããŠããŸããããåãåé¡ã§åãã¹ã¬ããã«æ»ã£ãŠããŸããã
@sudomaximeããã¯ãã®åé¡ã®ç¯å²å€ã§ããã ECMAScriptãã¯ã©ã¹ã®this.constructor.
ã®ãšã€ãªã¢ã¹ãšããŠself.
ããã€ãã£ãã«ãµããŒãããŠããªãéãã TypeScriptã®èšèšç®æšã«åããŠå®è¡ãããŸãã self
ãäžè¬çãªå€æ°åã§ããå Žåã«çºçããŸãã
@ abdullah-kasimã®ãœãªã¥ãŒã·ã§ã³ã¯èª¬æã©ããã«æ©èœããããã§ããããžã§ããªãã¯ã¯ã©ã¹ã§æ©èœãããããšãã§ããŸããã
class Animal<A> {
public thing?: A;
static create<T extends typeof Animal>(this: T): InstanceType<T> {
return new this() as InstanceType<T>;
}
}
type Foo = {};
class Bunny extends Animal<Foo> {}
const bunny = Bunny.create(); // typeof bunny is Animal<unknown>
bunny.thing; // unknown :(
__ __
/_/| |\_\
|U|___|U|
| |
| , , |
( = Y = )
| ` |
/| |\
\| | | |/
(_|_|___|_|_)
'"' '"'
éãæªãã£ãã®ã§å°ãããã£ãŠã¿ãã®ã§ããããå®çŸå¯èœãã©ããã«ã€ããŠèããŠããã ããã°å¹žãã§ãã
@stevehansonããã¯ããªãã®ããã«åããŸããïŒ
class Animal<A> {
public thing?: A;
static create<T>(this: new () => T): T {
return new this() as T;
}
}
type Foo = {asd: 123};
class Bunny extends Animal<Foo> {
public hiya: string = "hi there"
}
const bunny = Bunny.create()
bunny.thing
const test = bunny.thing?.asd
const hiya = bunny.hiya
typescriptãã¬ã€ã°ã©ãŠã³ãã§ããããã¹ãããŸããã
ãã®ãªã³ã¯ã«è§ŠçºãããŸããïŒ
https://selleo.com/til/posts/gll9bsvjcj-generic-with-class-as-argument-and-returning-instance
ãããŠãTãã¯ã©ã¹èªäœã§ããããšãã©ã®ããã«æ瀺ããŠããã®ãããããŸããã ç·šéïŒãããèŠããŠããŸãããããµã€ã¬ã³ãthis
ãã©ã¡ãŒã¿ãŒã¯åžžã«ã¯ã©ã¹èªäœãæž¡ããããTãæ瀺ããããšãã§ããŸããã
@ abdullah-kasimããã¯ããŸããããŸããïŒ ãããããããšãïŒ ç§ã®ç¹å®ã®ã±ãŒã¹ã§ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒãåŒæ°ãåãã®ã§ãä»ã®èª°ããå©ããå Žåã«åããŠãããã¯ç§ã«ãšã£ãŠã¯ã©ã®ããã«èŠãããã§ããïŒ
static define<C, T, F = any, I = any>(
this: new (generator: GeneratorFn<T, F, I>) => C,
generator: GeneratorFn<T, F, I>,
): C {
return new this(generator);
}
ããã§ã®è§£æ±ºçã®ããã€ãã¯ã次ã®åŒæ°ãæž¡ãããšãã§ããªããããéçã²ãã¿ãŒã§ã¯æ©èœããŸããã
以äžã®äŸã§ã¯ã default
éçã²ãã¿ãŒã芪ã¯ã©ã¹ã«ç§»åããã«ã¯ã©ãããã°ããã§ããïŒ
class Letters {
alpha: string = 'alpha'
beta?: string
gamma?: string
static get default () {
return new this()
}
}
const x = Letters.default.alpha;
æ§æã®æ¹åãæ€èšããå Žåãããã¯æ€èšãã䟡å€ã®ããããšãããããŸããã
ããããé¢é£ããŠããïŒ@ abdullah-kasimã®äŸã«å¥ã®æœè±¡åã¬ã€ã€ãŒãè¿œå ããã®ã«åé¡ããããŸãã åºæ¬çã«ã Animal
ãã€ã³ã¿ãŒãã§ã€ã¹ã«å€æãã Bunny
ãç¬èªã®éçcreate()
$ãå®çŸ©ã§ããããã«ããããšæããŸãã
ãããå®éçãªäŸã§ãïŒãããŒã®ã¢ãããžãŒãæŸæ£ããããšãèš±ããŠãã ããïŒïŒã ããã€ãã®ç°ãªãããã¥ã¡ã³ãã¿ã€ããå®çŸ©ã§ããããã«ãããã®ã§ããããããããæååãããã¥ã¡ã³ãã€ã³ã¹ã¿ã³ã¹ã«å€æããéçãã¡ã¯ããªã¡ãœãããå®çŸ©ã§ããå¿ èŠããããŸãã ããã¥ã¡ã³ãã¿ã€ãã¯ãä»ã®ããã¥ã¡ã³ãã¿ã€ãã§ã¯ãªããããèªäœã®ããŒãµãŒã®ã¿ãå®çŸ©ããå¿ èŠãããããšã匷å¶ããããšæããŸãã
ïŒä»¥äžã®äŸã®ã¿ã€ãã¯å®å šã«ã¯æ£ãããããŸãããããŸãããã°ãç§ãéæããããšããŠããããšã¯ååã«æ確ã§ãïŒ
interface ParseableDoc {
parse<T>(this: new () => T, serialized:string): T|null;
}
interface Doc {
getMetadata():string;
}
// EXPECT: no error!
const MarkdownDoc:ParseableDoc = class implements Doc {
constructor(private meta:string){ };
getMetadata():string { return this.meta; };
static parse(serialized:string):typeof MarkdownDoc | null {
// do something specific
return null;
}
}
// EXPECT: type error, since class defines no static parse()
const MissingParseDoc:ParseableDoc = class implements Doc {
constructor(private meta:string){ };
getMetadata():string { return this.meta; };
}
// EXPECT: type error, since parse() should return a MismatchedDoc
const MismatchDoc: ParseableDoc = class implements Doc {
constructor(private meta:string){ };
getMetadata():string { return this.meta; };
static parse(serialized:string):typeof MismatchDoc | null {
// do something specific
return null;
}
}
ïŒç§ã¯æãïŒç§ã¯ãã®ãããªãã®ãæžãããšãã§ããããã«ãªãããã§ãïŒ
interface ParseableDoc {
getMetadata():string;
static parse<T extends ParseableDoc>(this: new () => T, serialized:string): T|null;
}
class MarkdownDoc implements ParseableDoc {
getMetadata():string { return ""; }
static parse(serialized:string):MarkdownDoc|null {
// do something specific
return null;
}
}
ããã§ãåé¿çãå¯èœãã©ããèããŠã¿ãŠãã ããã
ç·šéïŒå¯èœãªåé¿ç
StackOverflowã®å¥ã®ãŠãŒã¹ã±ãŒã¹
æ±çšã«ãã¯ã¢ããããŒãã«ã¯ã©ã¹ãèšèšããããã
// Generic part
abstract class Table<T extends Model> {
instances: Map<number, T> = new Map();
}
abstract class Model {
constructor(
public readonly id: number,
public table: Table<this> // Error
) {
table.instances.set(id, this);
}
}
// Example: a table of Person objects
class Person extends Model {
constructor(
id: number,
table: Table<this>, // Error
public name: string
) {
super(id, table);
}
}
class PersonTable extends Table<Person> {}
const personTable = new PersonTable();
const person = new Person(0, personTable, 'John Doe');
// Note: the idea of using `this` as generic type argument is to guarantee
// that other models cannot be added to a table of persons, e.g. this would fail:
// class SomeModel extends Model { prop = 0; }
// const someModel = new SomeModel(1, person.table);
// ^^^^^^^^^^^^
@ Think7ã¯2016幎5æ29æ¥ã«ã³ã¡ã³ãããŸãã
ð°ããããŸã ä¿®æ£/è¿œå ãããŠããªãããšãä¿¡ããããšãã§ããŸãã.....
ãã
2020幎ã¯ããã«ãããŸãïŒ
ããã¯ã°ãããŠéåžžèã§ãã 2020幎ã§ãã4幎åŸããªããããä¿®æ£ãããªãã£ãã®ã§ããïŒ
ã®ãããªãã®ãå®è£ ããŠã¿ãŸããã
class Model {
static create(){
return new static()
}
//or
static create(): this {
return new this()
}
}
class User extends Model {
//...
}
let user = new User.create() // type === User
æãåèã«ãªãã³ã¡ã³ã
ãã®åé¡ã解決ãããçç±ã¯ãããŸããïŒ
ç§ã®æèŠã§ã¯ããããéååŠã§ã¯æ©èœããªããšããäºå®ã¯ãåºæ¬çã«ãã®æ©èœãDOAã«ããŸãã ãããŸã§ãã€ã³ã¹ã¿ã³ã¹ã¡ã³ããŒã§ãããå®éã«å¿ èŠãšããããšã¯ãããŸããã§ããããéçãªåŠçã®ã·ã¹ãã ã¯åæã®é ã«å®æããŠãããããéçãªãã®ã«ã€ããŠã¯æ°é±éããšã«å¿ èŠã§ããã ãã®æ©èœãçºè¡šããããšãã¯å€§åã³ã§ãããããã®åŸãã€ã³ã¹ã¿ã³ã¹ã¡ã³ããŒã§ã®ã¿æ©èœããããšã«æ°ä»ãããšãã«å€±æããŸããã
ãŠãŒã¹ã±ãŒã¹ã¯éåžžã«åºæ¬çã§éåžžã«äžè¬çã§ãã åçŽãªãã¡ã¯ããªã¡ãœãããèããŠã¿ãŸãããã
ãã®æç¹ã§ãç§ã¯åç¶æ¿è ã«
static create()
ã¡ãœãããéããã£ã¹ããŸãã¯ãã€æšãŠããããšã«é Œã£ãŠããŸãã ãã®æ©èœããªãããšã¯ãèšèªã®ããªã倧ããªå®å šæ§ã®ç©Žã®ããã«æããŸãã