2015-12-04 5 views
3

При попытке преобразовать простой файл JS в TS с неявным «любой» отключен, я получаю эту ошибку:Как преобразовать новый синтаксис SomeFunction() в TypeScript?

error TS7009: 'new' expression, which lacks a constructor signature, implicitly has an 'any' type.

interface Logger { 
    new():any; 
    //():any; // "Callable" syntax. same error. 
    //new():LoggerInstance; //Same error. 
} 
interface LoggerInstance { 
} 

function Logger(): void { 
} 


var defaultLogger: LoggerInstance = new Logger();//error TS7009 
//var defaultLogger: LoggerInstance = <any>new Logger();//same error 
//var defaultLogger: LoggerInstance = <LoggerInstance >new Logger();//same error 

Я не вижу, как сделать это без преобразования функции регистратора в класс.

Без каких-либо неявных отключений компилятор машинописного текста делал какие-либо предложения по улучшению, поэтому я хотел бы оставить эту настройку включенной.

Обновление: Если я удалю «новое» из интерфейса Logger, а затем произведу результат нового Logger (...), его можно скомпилировать в полном файле, но в моем более маленьком тестовом примере я продолжаю чтобы получить ту же ошибку.

Обновление 2 Хорошо, я думаю, что случается, что предупреждения об ошибках исчезают, когда плагин, который краснеет, подчеркивает синтаксические ошибки. Я думаю, что этот стиль создания объекта должен быть запрещен, если «неявный какой-либо» отключен.

+1

Так почему бы не превратить его в к классу? – Nypan

+0

Когда это класс, он становится IIFE, возвращая объект, а не «новую функцию», я не знаю, какое влияние это может иметь. Если компилятор скрипта типа требует в процессах аннотации, отбрасывая код и используя совершенно разные структуры, я мог бы также использовать CoffeeScript или Python или что у вас есть. – MatthewMartin

+0

В чем разница между возвратом функции new'd и объектом? Я не понял вашего ответа Нипану. –

ответ

4

Короткий плохой ответ

interface IPerson { 
    name: string; 
} 

var person = function(name: string) : void { 
    this.name = name; 
} 

let funcPerson = <IPerson>(new (<any>(person("John Doe")))); 

Это работает и собирает с флагом noImplicitAny.

Чем дольше лучше ответ

Просто преобразовать его в класс:

class person { 
    constructor(public name: string) { } 
} 

let classPerson = person("John Doe"); 

Это компилирует:

var person = (function() { 
    function person(name) { 
     this.name = name; 
    } 
    return person; 
})(); 
var classPerson = new person("Jane Doe"); 

Это IIFE, который в простейшем случае выше не имеет значения, что когда-либо сравнивалось с реализацией var person = function.... Это точно то же самое.

Преобразование новой функции в класс полезно. Это делает код доступным для чтения, его легче реорганизовать и проще расширять/модифицировать в будущем. Он также имеет лучшую информацию о типе (в этом случае вам даже не нужен интерфейс).

Короче говоря, я не могу использовать новую версию функции над версией класса этого решения. Обе версии приводят к идентичным объектам (см. classPerson и funcPerson выше).

Третий вариант

Если у вас есть рабочий .js файл, который вы хотите использовать с машинописи вариантом является написание .d.ts файла. В этом случае вы можете сделать что-то вроде этого:

person.js

var person = function(name) { 
    this.name = name; 
} 

person.d.ц

interface PersonStatic { 
    name:string; 
    new(name: string) : PersonStatic; 
} 
declare var person: PersonStatic; 

При использовании этого вы могли бы сделать:

/// <reference path="your.d.ts"/> 
var p = new person("Jane Doe"); 

и он будет работать.

В этом случае файл person.js должен присутствовать во время выполнения для правильного выполнения javascript. Файл .d.ts выше является основным примером, если вы решите пойти по этой дороге, я рекомендую сначала прочитать о создании файлов .d.ts перед загрузкой.

+0

Спасибо, это имеет смысл. Я могу понять, почему я не мог наткнуться на синтаксис для (новый ( (человек («Джон Доу»)))); – MatthewMartin

+1

'new ( (person ..." ломается для меня, видимо, из-за дополнительной скобки, которая хранится в сгенерированном JS 'new (person',' this' 'undefined' внутри' person'. TS 2.1.4. –

+0

Да, просто для уточнения ( (синтаксис человека ... нарушает JavaScript javascript - он делает для меня тоже с (...) не конструктор – PandaWood

1

Define the type and type's constructor structures. Interfaces would work just fine.

type PersonType = { 
    name: string; 
    greet: (otherPerson: PersonType) => string; 
    selfIntroduce:() => string; 
} 

//ordinary functions are called with or without the "new" operator and 
//the constructor's type must indicate both signatures 

type PersonTypeConstructor = { 
    (this: PersonType, name: string): void; //<- "this" could be omitted here 
    new(name: string): PersonType; // <- "this" must not appear here 
} 

Define the function that will be used as the constructor. this must be specified as the first parameter(since TS 2.0) so the compiler will not complain when the noImplicitThis flag is set true.

const Person = (function Person(this: PersonType, name: string) { 
    this.name = name; 
}) as PersonTypeConstructor; // <- cast the constructor here so no other cast will be necessary. 

Person.prototype.greet = function (otherPerson: PersonType) { 
    return `Hello, ${otherPerson.name}!`; 
}; 

Person.prototype.selfIntroduce = function() { 
    return `Hello, my name is ${this.name}.`; 
}; 

let peggySue = new Person("Peggy Sue"); 
let maryAnn = new Person("Mary Ann"); 

console.log(maryAnn.selfIntroduce()); 
console.log(peggySue.greet(maryAnn)); 
Смежные вопросы