Javascript Typescript:为什么它试图针对所有函数重载调整参数类型?
我正在寻找一位打字大师来帮助我。我试图在Typescript中实现一些一元行为。我有一个数据类型,可以有4种不同的形状。我希望能够拥有基本的一元函数,如Javascript Typescript:为什么它试图针对所有函数重载调整参数类型?,javascript,typescript,types,functional-programming,monads,Javascript,Typescript,Types,Functional Programming,Monads,我正在寻找一位打字大师来帮助我。我试图在Typescript中实现一些一元行为。我有一个数据类型,可以有4种不同的形状。我希望能够拥有基本的一元函数,如map和flatMap 我一直在努力使typescript编译器对我的类型感到满意,我尝试了多种方法(使用类、抽象类、简单类型等),但这是我想到的最好的方法 export namespace Data { export type Initial<T,E> = { kind: 'initial' } export type Lo
map
和flatMap
我一直在努力使typescript编译器对我的类型感到满意,我尝试了多种方法(使用类、抽象类、简单类型等),但这是我想到的最好的方法
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'}
// Map
export function map<T,U,E>(fn: (t: T) => U, data: Loaded<T,E>): Loaded<U,E>;
export function map<T,U,E>(fn: (t: T) => U, data: Failed<T,E>): Failed<U,E>;
export function map<T,U,E>(fn: (t: T) => U, data: Loading<T,E>): Loading<U,E>;
export function map<T,U,E>(fn: (t: T) => U, data: Initial<T,E>): Initial<U,E>;
export function map<T,U,E>(fn: (t: T) => U, data: Data<T,E>) {
if(isLoaded(data)) {
return loadedOf(fn(data.value))
}
return data
}
}
const a = Data.map(x => x, Data.loadedOf('hi'))
const b = Data.map(x => x, Data.loadingOf<string>())
const c = Data.map(x => x, Data.initialOf<string>())
const d = Data.map(x => x, Data.failedOf<string>())
const datas:Data.Data<string>[] = [a,b,c,d]
datas.map(data => Data.map(x=>x, data))
如果我交换重载的顺序,它只会将错误代码的最后一行从initial
更改为其他内容
我不明白为什么它对这些类型不满意。数据是否完全合适?为什么要尝试使参数类型与所有可能重载的参数类型相匹配
如果我删除带有子类型的签名,只保留最通用的一个,那么它将停止抱怨,但会使类型松散。任何子类型都将被强制为较松散的类型Data
,这是我不想要的。实现签名不参与重载解决,如上一段所述
如果您需要通用版本的映射
,拥有具有通用签名的实现是不够的,您必须显式地添加它,因为单独的声明只会重载:
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....
}
导出功能图(fn:(t:t)=>U,数据:数据):数据;
导出功能图(fn:(t:t)=>U,数据:数据){
//在这里实现。。。。
}
如上一段所述,实现签名不参与过载解决
如果您需要通用版本的映射
,拥有具有通用签名的实现是不够的,您必须显式地添加它,因为单独的声明只会重载:
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....
}
导出功能图(fn:(t:t)=>U,数据:数据):数据;
导出功能图(fn:(t:t)=>U,数据:数据){
//在这里实现。。。。
}