SHOW:
|
|
- or go back to the newest paste.
| 1 | // TypeScript中的静态函数的interface的变通实现方法 | |
| 2 | // 进一步参考:https://stackoverflow.com/questions/33719459/how-to-declare-an-interface-with-static-method?lq=1 | |
| 3 | ||
| 4 | /** | |
| 5 | * TypeScript Constructor Interfaces Proposal | |
| 6 | * | |
| 7 | * Author: Reed Spool | |
| 8 | */ | |
| 9 | ||
| 10 | /** | |
| 11 | * Root interface for Constructor Interfaces. This is a workaround for | |
| 12 | * TypeScript's lack of "static" methods for classes. | |
| 13 | * | |
| 14 | * Based on StackOverflow user chris's solution. See | |
| 15 | * https://stackoverflow.com/a/43484801/1037165 | |
| 16 | * | |
| 17 | * @interface IConstructor | |
| 18 | * @template InstanceInterface | |
| 19 | */ | |
| 20 | interface IConstructor<InstanceInterface> | |
| 21 | {
| |
| 22 | /** | |
| 23 | * Explicitly typed constructor is required, so make an extremely permissive | |
| 24 | * declaration that can be refined in subclasses. | |
| 25 | * | |
| 26 | * @constructor | |
| 27 | */ | |
| 28 | new (...args : any[]) : InstanceInterface; | |
| 29 | } | |
| 30 | ||
| 31 | /** | |
| 32 | * That's ALL for the definition. What follows is a comprehensive usage | |
| 33 | * example. | |
| 34 | */ | |
| 35 | ||
| 36 | // Create a Constructor Interface by extending IConstructor and | |
| 37 | // specifiying your Instance Interface. Keep your class open for | |
| 38 | // extension with "T extends ...". | |
| 39 | interface CMyClass<T extends IMyClass> extends IConstructor<T> | |
| 40 | {
| |
| 41 | // Specify constructor parameters safely, staying open for extension | |
| 42 | // by specifying any variatic arguments. You don't need to specify | |
| 43 | // a constructor though. | |
| 44 | new (instanceValue : string, ...args : any[]) : T; | |
| 45 | ||
| 46 | // Properties on Constructor Interfaces can be accessed by the | |
| 47 | // Class object. | |
| 48 | aClassProperty : string; | |
| 49 | ||
| 50 | // This is useful for static factory methods. | |
| 51 | aClassMethod () : T | |
| 52 | } | |
| 53 | ||
| 54 | // Create a normal Instance Interface. IConstructor doesn't require | |
| 55 | // or restrict anything here. You could use anything, including | |
| 56 | // `Object` or `any` | |
| 57 | interface IMyClass | |
| 58 | {
| |
| 59 | } | |
| 60 | ||
| 61 | // This is the hackish part: Your class must be anonymous so that | |
| 62 | // you can specify the type of the variable that holds it. So make a | |
| 63 | // `const` variable of your Constructor Interface's type set to a new | |
| 64 | // anonymous class which implements your Instance Interface. | |
| 65 | export const MyClass : CMyClass<IMyClass> = class implements IMyClass | |
| 66 | {
| |
| 67 | // The constructor must satisfy CMyClass's `new` signature. | |
| 68 | constructor (instanceValue : string, ...args : any[]) | |
| 69 | {
| |
| 70 | } | |
| 71 | ||
| 72 | // We can use the built-in JS `static` keyword to satisfy the interface | |
| 73 | // of CMyClass | |
| 74 | static aClassProperty : string = "myProp"; | |
| 75 | static aClassMethod () : IMyClass { return new MyClass(); }
| |
| 76 | } |