[英]Syntax error for Typescript arrow functions with generics
首先,這里有一個類似的問題: what-is-the-syntax-for-typescript-arrow-functions-with-generics
但是,我想知道語法錯誤的罪魁禍首 。
我正在使用外部庫,這就是定義文件(index.d.ts)的樣子:
declare namespace Student {
export interface Lecture {
lectureName: string;
}
export interface Student {
new (): Student;
on1(eventName: string, callback: (<T>(lecture: T, oldLecture: T) => void) |
((name: string, ...args: any[]) => void)): void;
on2(eventName: string, callback: (<T>(lecture: T, oldLecture: T) => void)): void;
}
}
declare var Student: Student.Student;
declare module "student" {
export = Student;
}
請注意,有兩個函數: Student.Student中的 on1和on2 - 函數on1有更多代碼。
所以這是我的代碼示例。
import * as Student from 'student';
import { Lecture } from 'student';
export class MyStudent {
student: Student.Student;
constructor() {
this.student = new Student();
this.student.on1('test', (lecture: Lecture, oldLecture: Lecture) => {
// Argument of type error
});
this.student.on2('test', (lecture: Lecture, oldLecture: Lecture) => {
// Argument of type error
});
}
}
函數on1給出了以下錯誤:
類型'(講座:講座,oldLecture:Lecture)=> void'的參數不能賦予類型'的參數((講座:T,oldLecture:T)=> void)| ((name:string,... args:any [])=> void)'。 類型'(講座:講座,oldLecture:Lecture)=> void'不能分配給'(name:string,... args:any [])=> void'。 參數“講座”和“名稱”的類型不兼容。 類型'字符'不能分配給'Lecture'類型。
函數on2給出以下錯誤:
類型'(講座:講座,oldLecture:Lecture)=> void'的參數不能分配給'(講座:T,oldLecture:T)=> void'類型的參數。 參數'講座'和'講座'的類型是不相容的。 類型'T'不能分配給'Lecture'類型。
我認為這個例子是實現代碼的正確方法 - 但為什么會出錯呢?
import * as Student from 'student';
import { Lecture } from 'student';
export class MyStudent {
student: Student.Student;
constructor() {
this.student = new Student();
this.student.on1('test', <Lecture>(lecture: Lecture, oldLecture: Lecture) => {
lecture.lectureName;
// Error: Property 'lectureName' does not exist on type 'Lecture'
});
this.student.on2('test', <Lecture>(lecture: Lecture, oldLecture: Lecture) => {
lecture.lectureName;
// Error: Property 'lectureName' does not exist on type 'Lecture'
});
}
}
在這個例子中,我將<Lecture>
放在箭頭函數前面 - 所以實現中沒有錯誤,但現在我根本不能使用lecture.lectureName
。 為什么?
import * as Student from 'student';
import { Lecture } from 'student';
export class MyStudent {
student: Student.Student;
constructor() {
this.student = new Student();
this.student.on1('test', <T extends Lecture>(lecture: T, oldLecture: T) => {
lecture.lectureName; // Yay! No problem!
});
this.student.on2('test', <T extends Lecture>(lecture: T, oldLecture: T) => {
// Argument of type error
});
}
}
所以這個例子有正確的答案 - 但是,函數on2仍然給出了類型錯誤的參數,就像案例1的例子一樣。 不應該沒關系,因為on1功能還可以嗎?
import * as Student from 'student';
import { Lecture } from 'student';
export class MyStudent {
student: Student.Student;
constructor() {
this.student = new Student();
this.student.on1('test', () => () => (lecture: Lecture, oldLecture: Lecture) => {
lecture.lectureName; // Yay! No error!
});
this.student.on2('test', () => () => (lecture: Lecture, oldLecture: Lecture) => {
lecture.lectureName; // Yay! No error!
});
}
}
我偶然發現了這個解決方案 - 兩個功能都運行正常。 但我不知道為什么這樣做。
我花了一些時間試圖通過查看這些引用來找出確切的原因(因為我喜歡TypeScript):
但我仍然想知道這個問題的確切原因。
我知道這不能直接回答你的問題,但你可以通過使用類方法來避免這個問題,而不是嵌套的匿名回調(感覺非常2015)
type Handler = <T>(t: T) => void;
class Student {
on1(s:string, callback:Handler) : void {
callback<string>("hi")
}
}
class MyStudent {
student: Student
constructor() {
this.student = new Student()
this.student.on1('test', this.log)
}
log<T>(t:T) : void {
console.log("hi " + t)
}
}
您對如何聲明泛型函數以及如何調用泛型函數感到有點困惑。
您可以用以下方法總結您的問題:
// Define the Identity function type
// The result type = input type
type TIdentityFunc = <T>(input: T) => T;
// Implement the TIdentity function
// We followed the rule.
const identityImpl: TIdentityFunc = <T>(input: T) => input;
// Now we call this implementation
const num = identity(5); // num is always number
const str = identity('hi') // str is always a string
在您的示例中,您實現了請求的回調,這意味着當有人調用此回調時,她將知道參數類型。
記住,你沒有打電話給回調,你只是在實現它!
所以你的代碼應該是這樣的:
import * as Student from 'student';
import { Lecture } from 'student';
export class MyStudent {
student: Student.Student;
constructor() {
this.student = new Student();
this.student.on1('test', <T>(l1: T | string, l2: T, ...args) => {
// This is a bit complicated overloading,
// But it follows the rules of the declaration
});
this.student.on2('test', <T>(lecture: T, oldLecture: T) => {
// Your only assumption is that lecture, and oldLecture are the same type
});
}
}
問題是打字是在錯誤的地方聲明通用:
declare interface Lecture {
lectureName: string;
}
declare interface Student {
new (): Student;
on1<T>(eventName: string, callback: ((lecture: T, oldLecture: T) => void) |
((name: string, ...args: any[]) => void)): void;
on2<T>(eventName: string, callback: (lecture: T, oldLecture: T) => void): void;
}
let s: Student;
s.on1('x', (a: Lecture, b: Lecture) => {
})
s.on2('y', (a: string, b: string) => {
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.