我希望能够说一个函数只返回扩展某个给定类的类。
我尝试的是定义类型AnimalClass
interface AnimalClass {
new( name : String ) : Animal ;
}
我认为这意味着AnimalClass的实例是具有构造函数的类(或者我应该说"是构造函数"),它接受String并构造Animal的实例。
但是下面的代码,我认为有错误,用tsc版本1.7.5编译。
interface AnimalClass {
new( name : String ) : Animal ;
}
abstract class Animal {
name : String ;
constructor( name : String ) { this.name = name }
abstract kind() : String ;
}
class Lion extends Animal {
kind() : String { return "lion" ; }
}
function getAnimalClass() : AnimalClass {
return Lion ; // Shouldn't this be an error?
}
function makeAnimal() : Animal {
const klass = getAnimalClass() ;
return new klass( "bob" ) ;
}
var a = makeAnimal() ;
console.log( a.name + " is a " + a.kind() ) ;
我认为这是错误的,因为在函数getAnimalClass
中我需要Lion
是AnimalClass
的实例,但是Lion
没有带{的String
的构造函数{1}}。
或许Lion
从Animal
继承构造函数。这可以解释为什么没有错误以及为什么代码运行和打印" bob是狮子"
但不!如果我删除Animal
中的构造函数,代码仍会编译。 (虽然现在它打印" undefined是狮子")。
所以主要的问题是:
次要问题:
为什么上面的代码没有错误?
是否在TypeScript中继承了构造函数?
答案 0 :(得分:3)
当你有一个由包含参数的接口支持的方法时,调用者将被要求传递一个参数,但是被调用者不需要使用它。
因此,如果接口需要传递参数,则省略它是错误的。
interface Example {
(x: number): void;
}
var giveMeANumber: Example = function (num: number) {
}
giveMeANumber(); // Error
但忽略已传递的参数并不是错误。
interface Example {
(x: number): void;
}
var giveMeANumber: Example = function () {
}
giveMeANumber(15); // No Error
所以在你的情况下,你已经定义了必须将一个字符串传递给它们的构造函数。所有动物都必须传递一个字符串 - 这是您定义的常用签名。在狮子会的情况下,字符串被忽略(因为它不需要)。
在您的示例中,如果查看生成的代码,您将看到当您在子类中省略构造函数时,会为您生成一个:
function Lion() {
_super.apply(this, arguments);
}
它使用了神奇的arguments
,这意味着名称实际上已经到了基类。你可以通过序列化狮子来测试这个:
var lion = new Lion('Clarence');
alert(JSON.stringify(lion));
如果你在狮子类中添加了一个构造函数,编译器会告诉你需要在构造函数中调用super
,然后你必须将一个字符串传递给它:
class Lion extends Animal {
constructor() {
super('HARD-CODED');
}
kind() : String { return "lion" ; }
}
因此,您的类型是准确的,但TypeScript实际应用此信息,并尊重JavaScript范例。
答案 1 :(得分:1)
首先,将String
类型更改为string
。 string
用于基本类型,String
表示String
接口。
构造函数是否在TypeScript中继承?
是。您可以进行快速测试以查看:
abstract class Animal {
constructor(name: string) {}
}
class Lion extends Animal {
}
new Lion(); // error
如何编写描述对象的类型,这些对象是扩展给定类的类,并为构造函数提供给定的参数列表?
你这样做的方式很好。对于新签名中指定的返回类型,它始终是错误的,这对于大多数情况都是足够的。例如,传递一个具有与Animal
不同结构的类将会出错。
正如您已经发现的那样,在某些情况下它并没有发生错误,而且您已经发现其中一种情况。当新签名的返回类型匹配时似乎没有错误,但参数的数量不同。这就是为什么在删除构造函数时它不会出错的原因。但请注意,如果返回类型匹配,则会出错,但至少有一个参数的类型不同。