带有扩展接口的参数的 Typescript 通用回调,TS2345
Typescript generic callback with arguments that extend an interface, TS2345
我如何创建一个接受参数的回调,其中参数可以是任何扩展某些接口的东西,但除此之外我不知道确切的类型?
例如
const fnct = function( data: DataAny, callback: GenericCallback<DataAny> ): void {
callback( data );
};
// DataAny here should be like "argument type that can be anything but has to extend DataAny"
例子
更具体地说,我怎样才能避免这里最后两行的打字错误
(从下往上阅读可能最容易):
// -- unchangeable interface, comes from external library --
interface DataAny {
type: string;
[more: string]: any;
}
// -- my interfaces / types --
interface DataBook extends DataAny { pages: number }
interface DataWater extends DataAny { liters: number }
type GetQuantity<D> = ( data: D ) => void; // callback function type
// -- generic function --
const genericQuantityInfo = function( data: DataAny, f: GetQuantity<DataAny> ): void {
console.log('quantity: ', f( data ));
};
// -- data --
const book: DataBook = { type: 'book', pages: 303 };
const water: DataWater = { type: 'water', liters: 12 };
// -- callbacks --
const getQuantityBook: GetQuantity<DataBook> = function( data: DataBook ){ return data.pages + ' pages'; };
const getQuantityWater: GetQuantity<DataWater> = function( data: DataWater ){ return data.liters + ' liters'; };
// -- calls --
genericQuantityInfo( book, getQuantityBook ); // <-- error TS2345: 'GetQuantity<DataBook>' is not assignable to 'GetQuantity<DataAny>'. 'pages' is missing in 'DataAny' but required in 'DataBook'
genericQuantityInfo( water, getQuantityWater ); // <-- error (similar to above)
不想要
请注意,我可以 不 传递特定类型,例如 genericQuantityInfo<DataBook>
此处(有效):
const genericQuantityInfo = function<T>( data: T, f: GetQuantity<T> ): void { console.log('quantity: ', f( data )); };
genericQuantityInfo<DataBook>( book, getQuantityBook );
genericQuantityInfo<DataWater>( water, getQuantityWater );
我不能这样做的原因是我的用例实际上更复杂,使用创建者函数,我不想传递所有可能的类型<DataBook | DataWater | ...
(我也无法让它工作)。喜欢:
const creator = function<T>(){
return function( data: T, f: GetQuantity<T> ): void {
console.log('quantity: ', f( data ));
};
};
creator<DataBook | DataWater /* | ... */ >()(book, getQuantityBook); // <-- still error anyway
但是由于我在这里进行了很多简化,所以也欢迎任何关于我误解的地方的想法。谢谢。
我想我明白了:
与其键入 DataAny
,不如尝试键入 T extends DataAny
,这意味着任何具有 DataAny
道具的东西。
interface DataAny {
type: string;
[more: string]: any;
}
// -- my interfaces / types --
interface DataBook extends DataAny { pages: number }
interface DataWater extends DataAny { liters: number }
type GetQuantity<D extends DataAny> = ( data: D ) => void; // callback function type
// -- generic function --
const genericQuantityInfo = function<T extends DataAny>( data: T, f: GetQuantity<T> ): void {
console.log('quantity: ', f( data ));
};
// -- data --
const book: DataBook = { type: 'book', pages: 303 };
const water: DataWater = { type: 'water', liters: 12 };
// -- callbacks --
const getQuantityBook: GetQuantity<DataBook> = function( data: DataBook ){ return data.pages + ' pages'; };
const getQuantityWater: GetQuantity<DataWater> = function( data: DataWater ){ return data.liters + ' liters'; };
// -- calls --
genericQuantityInfo( book, getQuantityBook ); // OK
genericQuantityInfo( water, getQuantityWater ); // OK
我如何创建一个接受参数的回调,其中参数可以是任何扩展某些接口的东西,但除此之外我不知道确切的类型?
例如
const fnct = function( data: DataAny, callback: GenericCallback<DataAny> ): void {
callback( data );
};
// DataAny here should be like "argument type that can be anything but has to extend DataAny"
例子
更具体地说,我怎样才能避免这里最后两行的打字错误
(从下往上阅读可能最容易):
// -- unchangeable interface, comes from external library --
interface DataAny {
type: string;
[more: string]: any;
}
// -- my interfaces / types --
interface DataBook extends DataAny { pages: number }
interface DataWater extends DataAny { liters: number }
type GetQuantity<D> = ( data: D ) => void; // callback function type
// -- generic function --
const genericQuantityInfo = function( data: DataAny, f: GetQuantity<DataAny> ): void {
console.log('quantity: ', f( data ));
};
// -- data --
const book: DataBook = { type: 'book', pages: 303 };
const water: DataWater = { type: 'water', liters: 12 };
// -- callbacks --
const getQuantityBook: GetQuantity<DataBook> = function( data: DataBook ){ return data.pages + ' pages'; };
const getQuantityWater: GetQuantity<DataWater> = function( data: DataWater ){ return data.liters + ' liters'; };
// -- calls --
genericQuantityInfo( book, getQuantityBook ); // <-- error TS2345: 'GetQuantity<DataBook>' is not assignable to 'GetQuantity<DataAny>'. 'pages' is missing in 'DataAny' but required in 'DataBook'
genericQuantityInfo( water, getQuantityWater ); // <-- error (similar to above)
不想要
请注意,我可以 不 传递特定类型,例如 genericQuantityInfo<DataBook>
此处(有效):
const genericQuantityInfo = function<T>( data: T, f: GetQuantity<T> ): void { console.log('quantity: ', f( data )); };
genericQuantityInfo<DataBook>( book, getQuantityBook );
genericQuantityInfo<DataWater>( water, getQuantityWater );
我不能这样做的原因是我的用例实际上更复杂,使用创建者函数,我不想传递所有可能的类型<DataBook | DataWater | ...
(我也无法让它工作)。喜欢:
const creator = function<T>(){
return function( data: T, f: GetQuantity<T> ): void {
console.log('quantity: ', f( data ));
};
};
creator<DataBook | DataWater /* | ... */ >()(book, getQuantityBook); // <-- still error anyway
但是由于我在这里进行了很多简化,所以也欢迎任何关于我误解的地方的想法。谢谢。
我想我明白了:
与其键入 DataAny
,不如尝试键入 T extends DataAny
,这意味着任何具有 DataAny
道具的东西。
interface DataAny {
type: string;
[more: string]: any;
}
// -- my interfaces / types --
interface DataBook extends DataAny { pages: number }
interface DataWater extends DataAny { liters: number }
type GetQuantity<D extends DataAny> = ( data: D ) => void; // callback function type
// -- generic function --
const genericQuantityInfo = function<T extends DataAny>( data: T, f: GetQuantity<T> ): void {
console.log('quantity: ', f( data ));
};
// -- data --
const book: DataBook = { type: 'book', pages: 303 };
const water: DataWater = { type: 'water', liters: 12 };
// -- callbacks --
const getQuantityBook: GetQuantity<DataBook> = function( data: DataBook ){ return data.pages + ' pages'; };
const getQuantityWater: GetQuantity<DataWater> = function( data: DataWater ){ return data.liters + ' liters'; };
// -- calls --
genericQuantityInfo( book, getQuantityBook ); // OK
genericQuantityInfo( water, getQuantityWater ); // OK