使用带 void 的函数接口时出现意外的打字稿编译器行为
unexpected typescript compiler behavior when using a function interface with void
如果我用 return type as number 定义一个函数接口,编译器会警告我
interface RequestHandler {
(): number
}
// the compiler will prompt an error
// because " Type '() => boolean' is not assignable to type 'RequestHandler'"
const handler: RequestHandler = function (): boolean {
return false
}
但是,如果我这样做,编译器似乎没问题
interface RequestHandler {
(): void
}
const handler: RequestHandler = function (): boolean {
return false
}
起初,我的猜测是一个带有 void return 类型的函数将接受任何 return 类型,根据这个是错误的:
// error TS2322: Type 'boolean' is not assignable to type 'void'
function foo(): void {
return true
}
我猜我的假设不成立,谁能解释这种行为?
编辑
ABOS 的回答启发了我找到更多关于这种行为的信息
我会放一个新的代码片段作为演示
class Animal {
eat() {}
}
// Dog is a subtype of Animal
class Dog extends Animal {
bark() {}
}
interface AnimalBuilder {
(): Animal
}
interface DogBuilder {
(): Dog
}
// DogBuilder is a subtype of Animal Builder
declare let animalBuilder: AnimalBuilder
declare let dogBuilder: DogBuilder
// this demonstrate "co-variance"
animalBuilder = dogBuilder // Ok
dogBuilder = animalBuilder // Error
interface AnimalFeeder {
(animal: Animal): void
}
interface DogFeeder {
(dog: Dog): void
}
// ...while AnimalFeeder is a subtype of DogFeeder (under "strictFunctionTypes")
// this is called "contra-variance"
// Although counter-intuitive at first glance, it ensures stronger type safety
declare let animalFeeder: AnimalFeeder
declare let dogFeeder: DogFeeder
// "contravariance"
dogFeeder = animalFeeder // Ok
animalFeeder = dogFeeder // Error when "--strictFunctionTypes"
// Ok when "strictFunctionTypes" is set to false, bi-variance
我的理解:有两种不同的类型兼容性检查。
为了
const handler: RequestHandler = function (): boolean {
return false
}
根据 Comparing two functions,这里发生的是 return 类型 boolean 的函数可分配给 void。请注意本节底部的示例和语句“类型系统强制源函数的 return 类型是目标类型的 return 类型的子类型。”在这种情况下,void 是 boolean 的子类型。
为了
// error TS2322: Type 'boolean' is not assignable to type 'void'
function foo(): void {
return true
}
这里发生的是数据类型比较,与第一种情况不同。所以它会像预期的那样抱怨不匹配的类型。
如果我用 return type as number 定义一个函数接口,编译器会警告我
interface RequestHandler {
(): number
}
// the compiler will prompt an error
// because " Type '() => boolean' is not assignable to type 'RequestHandler'"
const handler: RequestHandler = function (): boolean {
return false
}
但是,如果我这样做,编译器似乎没问题
interface RequestHandler {
(): void
}
const handler: RequestHandler = function (): boolean {
return false
}
起初,我的猜测是一个带有 void return 类型的函数将接受任何 return 类型,根据这个是错误的:
// error TS2322: Type 'boolean' is not assignable to type 'void'
function foo(): void {
return true
}
我猜我的假设不成立,谁能解释这种行为?
编辑 ABOS 的回答启发了我找到更多关于这种行为的信息 我会放一个新的代码片段作为演示
class Animal {
eat() {}
}
// Dog is a subtype of Animal
class Dog extends Animal {
bark() {}
}
interface AnimalBuilder {
(): Animal
}
interface DogBuilder {
(): Dog
}
// DogBuilder is a subtype of Animal Builder
declare let animalBuilder: AnimalBuilder
declare let dogBuilder: DogBuilder
// this demonstrate "co-variance"
animalBuilder = dogBuilder // Ok
dogBuilder = animalBuilder // Error
interface AnimalFeeder {
(animal: Animal): void
}
interface DogFeeder {
(dog: Dog): void
}
// ...while AnimalFeeder is a subtype of DogFeeder (under "strictFunctionTypes")
// this is called "contra-variance"
// Although counter-intuitive at first glance, it ensures stronger type safety
declare let animalFeeder: AnimalFeeder
declare let dogFeeder: DogFeeder
// "contravariance"
dogFeeder = animalFeeder // Ok
animalFeeder = dogFeeder // Error when "--strictFunctionTypes"
// Ok when "strictFunctionTypes" is set to false, bi-variance
我的理解:有两种不同的类型兼容性检查。
为了
const handler: RequestHandler = function (): boolean {
return false
}
根据 Comparing two functions,这里发生的是 return 类型 boolean 的函数可分配给 void。请注意本节底部的示例和语句“类型系统强制源函数的 return 类型是目标类型的 return 类型的子类型。”在这种情况下,void 是 boolean 的子类型。
为了
// error TS2322: Type 'boolean' is not assignable to type 'void'
function foo(): void {
return true
}
这里发生的是数据类型比较,与第一种情况不同。所以它会像预期的那样抱怨不匹配的类型。