打字稿自定义工具,转换器,扩展名

时间:2017-01-28 17:51:20

标签: visual-studio typescript compilation visual-studio-code

我希望在151.101.40.209启动其转换过程之前更改/检查Fastly error: unknown domain: 151.101.40.209. Please check that this domain has been added to a service. 文件,类似于 Roslyn 为C#提供的内容。

这对静态类型检查很有用。例如,正确和简短的.ts实现需要在编译时进行代码更改/静态检查,因为可以使用Flow来完成:

tsc

然后自定义tsc转换器可以将代码修改为:

Immutable Record

立即看到自定义编译错误会很好,因为它现在使用Visual Studio和Visual Studio Code完成,它运行特殊@Record(Person) interface IPerson { givenName: string; familyName: string; } ,而不是webpack捆绑或自定义gulp任务的一部分。有一个Typescript的API,但如何使其与interface IPersonParams { givenName?: string; familyName?: string; } @Record() class Person { private readonly __givenName; private readonly __familyName; constructor(init) { this.__givenName = init.givenName; this.__familyName = init.familyName; } get givenName() { return this.__givenName; } get familyName() { return this.__familyName; } update(update: IPersonParams) { // ignore the bug when undefined param is passed return new Person({ givenName: update.givenName || this.__givenName, familyName: update.familyName || this.__familyName }); } } 中的tsc watch无缝合作?

使用示例进行更新

目标只是写

tsc
  1. 如前所示,将根据界面VS/VS Code/Atom自动生成课程@Record(Person) interface IPerson { givenName: string; familyName: string; }

  2. 可以实例化对象:

    Person

    任何不正确的属性都会引发编译错误:

    IPerson

    错误:属性' nonExistedProperty'类构造函数中不存在;
    错误:属性' givenName'在Person构造函数中是必需的;
    错误:属性' familyName'在Person构造函数中是必需的;

  3. 现有对象应该能够部分更新

    let instance = new Person({givenName: "Emma", familyName: "Watson"}); let instance = new Person({nonExistedProperty: "Emma"}); //error

    let instance = new Person({givenName: "Emma", familyName: "Watson"});
    instance.Update({givenName: "Luise"});

  4. 所有属性都是只读

    instance.givenName === "Luise"; //TRUE; instance.familyName === "Watson"; //TRUE;

    错误:属性' givenName'是readonly;

  5. let instance = new Person({givenName: "Emma", familyName: "Watson"});方法是自动生成的。它可以基于哈希或其他任何东西,但应该快速工作并提供深入检查。

    instance.givenName = "John"; //error
    Equals

    let instance1 = new Person({givenName: "Emma", familyName: "Watson"});

    它也可能有一个控制创建实例的地方,如果内部字典中存在具有相同参数的记录,那么它只返回对该对象的引用:

    let instance2 = new Person({givenName: "Emma", familyName: "Watson"});
    instance1.Equals(instance2); //TRUE

    let instance1 = new Person({givenName: "Emma", familyName: "Watson"});
    let instance2 = new Person({givenName: "Emma", familyName: "Watson"});

3 个答案:

答案 0 :(得分:1)

也许不是编写自己的打字稿(预处理器),而是使用TypeScript装饰器来实现目标。

此示例来自https://www.typescriptlang.org/docs/handbook/decorators.html

@sealed
class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

function sealed(constructor: Function) {
    Object.seal(constructor);
    Object.seal(constructor.prototype);
}

答案 1 :(得分:1)

这是我到目前为止所发现的。目前没有简单的方法(2017年)。

一种解决方案是创建一个使用Typescript API的自定义插件。它还将在自己的沙箱中第二次运行服务,同时在VS CodeAtomVS中使用TS服务。除此之外,每个IDE都需要将自己的插件创建为核心插件/服务之上的包装器。

通过这种方式,有些人已经制作了短片,例如vscode-ng-language-serviceng2linter

Microsoft拥有TypeScript可扩展性的#6508票证,这将使所请求的功能成为可能并且易于实现。

对于使用C#F#进行编程的用户,最好使用Roslyn的可能性,而不是等待TypeScript扩展。用C#编写的代码可以转换为TypeScript或JavaScript。它还为各种检查和自定义修改打开了广泛的可能性。如果.NETTypeScript/Javascript中存在相同的逻辑,当然它更接近DRY principleBridge.NET不使用Roslyn,但具有良好的实现。 .NET 4和Roslyn的Rosetta项目似乎是一个良好的开端。

答案 2 :(得分:1)

这是可能的,没有任何编译魔术。

外部库

declare function someGenericEqualsFn(a, b): boolean;
declare function makeCached<TResult, TFunc extends (...args) => TResult>(funcToCache: TFunc): TFunc;
declare function merge<T>(objectToUpdate: T, objectToMerge: Partial<T>);

我们的lib:

interface DataRecord<TRecord> {
    equals<TRecord>(other: TRecord): boolean;
    update(update: Partial<TRecord>);
}

function createDataRecord<TRecord>(data: TRecord): Readonly<TRecord> & DataRecord<TRecord> {
    const result: TRecord & DataRecord<TRecord> = <any>{};
    Object.keys(data).forEach(() => {

    });

    result.equals = function (other: TRecord) {
        return someGenericEqualsFn(result, other);
    };

    result.update = function (partial: Partial<TRecord>) {
        merge(result, partial);
    };

    return result;
}

我们的测试:

interface IPerson {
    givenName: string;
    familyName: string;
}

let instance = createDataRecord<IPerson>({givenName: "Emma", familyName: "Watson"});
instance = createDataRecord<IPerson>({nonExistedProperty: "Emma"}); // compiler error
instance.givenName = "John";             // compiler error
instance.update({givenName: "Emma"});     //   works!
instance.update({nonExistedProperty: "x"});      // compiler error

const createDataRecordOrGetCached = makeCached(createDataRecord);
let instance1 = createDataRecordOrGetCached({givenName: "Emma", familyName: "Watson"});
let instance2 = createDataRecordOrGetCached({givenName: "Emma", familyName: "Watson"});

instance1 == instance2; //TRUE
instance1 === instance2; //TRUE