Typescript通用回调,带有扩展接口的参数,TS2345

问题描述 投票:0回答:1

我如何创建一个带参数的回调,其中参数可以是扩展某个接口的任何东西,但除此之外我不知道确切的类型?

例如

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)

Not想要

请注意,我可以not传递特定的类型,例如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

但是我在这里做了很多简化,也欢迎任何关于我在哪里误解的想法。谢谢。

interface callback arguments extend typescript-generics
1个回答
0
投票

我想我明白了:

[而不是键入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

playground

© www.soinside.com 2019 - 2024. All rights reserved.