我正在寻找一个打字稿大师来帮助我解决这个问题。我正在尝试在 Typescript 中实现一些 monadic 行为。我有一个可以采用 4 种不同形状的数据类型。我希望能够拥有像mapand这样的基本一元函数flatMap。我一直在努力让打字稿编译器对我的类型感到满意,我尝试了多种方法(使用类、抽象类、简单类型等),但这是我想到的最好的方法。export namespace Data { export type Initial<T,E> = { kind: 'initial' } export type Loading<T,E> = { kind: 'loading' } export type Loaded<T,E> = { kind: 'loaded'; value: T } export type Failed<T, E> = { kind: 'failed'; error?: E } export type Data<T,E = any> = Failed<T,E> | Loaded<T,E> | Loading<T,E> | Initial<T,E> type Kind = Data<any,any>['kind'] // Instantiations export function loadingOf<T=any,E=any>():Loading<T,E> { return {kind: 'loading'}} export function initialOf<T=any,E=any>():Initial<T,E> { return {kind: 'initial'}} export function loadedOf<T=any,E=any>(value: T):Loaded<T,E> { return {kind: 'loaded', value}} export function failedOf<T=any,E=any>(error?: E):Failed<T,E> { return {kind: 'failed', error}} // Type guards export function isFailed<T,E>( data: Data<T,E>): data is Failed<T,E> { return data.kind === 'failed'} export function isLoaded<T,E>( data: Data<T,E>): data is Loaded<T,E> { return data.kind === 'loaded'} export function isInitial<T,E>( data: Data<T,E>): data is Initial<T,E> { return data.kind === 'initial'} export function isLoading<T,E>( data: Data<T,E>): data is Loading<T,E> { return data.kind === 'loading'}这当然是不完整的,因为 typescript 对 map 功能不满意如果我交换重载的顺序,它只会将错误代码的最后一行更改initial为其他内容。我不明白为什么它对这些类型不满意。不完全Data<T,E>合适?为什么要尝试拟合参数类型以匹配所有可能的重载的参数类型?如果我删除带有子类型的签名并只保留最通用的签名,那么它就会停止抱怨,但它会使类型变得松散。任何子类型都将被强制为其松散的类型Data<T,E>,这是我不想要的。
1 回答

冉冉说
TA贡献1877条经验 获得超1个赞
实现签名不参与重载决议,如本页最后一段所述。
如果您需要 的通用版本map,具有通用签名的实现是不够的,您必须显式添加它,作为单独的仅声明重载:
export function map<T,U,E>(fn: (t: T) => U, data: Data<T,E>): Data<U, E>;
export function map<T,U,E>(fn: (t: T) => U, data: Data<T,E>) {
// implementation here....
}
添加回答
举报
0/150
提交
取消