Typescript 这是打字脚本错误吗?“错误”;不可分配给“类型”;向对象添加额外属性时
我正在使用两个API,它们对经度坐标使用不同的属性名称:Typescript 这是打字脚本错误吗?“错误”;不可分配给“类型”;向对象添加额外属性时,typescript,typescript-typings,Typescript,Typescript Typings,我正在使用两个API,它们对经度坐标使用不同的属性名称:lon和lng。我正在编写一个转换器函数,它添加了可选的属性名,以便两个API中的位置可以互换使用 这个函数给出了一个错误,在我看来确实是一个bug。我知道很多解决方法,但我有兴趣了解发生此错误的原因。这是一只虫子,还是我在这里遗漏了什么 const fillLonLng1 = <T extends LatLng | LatLon>(loc: T): T & LatLon & LatLng => {
lon
和lng
。我正在编写一个转换器函数,它添加了可选的属性名,以便两个API中的位置可以互换使用
这个函数给出了一个错误,在我看来确实是一个bug。我知道很多解决方法,但我有兴趣了解发生此错误的原因。这是一只虫子,还是我在这里遗漏了什么
const fillLonLng1 = <T extends LatLng | LatLon>(loc: T): T & LatLon & LatLng => {
if ( isLatLon(loc) ) {
return {...loc, lng: loc.lon};
} else {
return {...loc, lon: loc.lng};
}
}
Typescript正确理解返回的值包含lat
和lon
,这两个值都是number
。我不明白这怎么可能不分配给LatLon
,定义如下:
interface LatLon {
lat: number;
lon: number;
}
const isLatLon=(loc:T):loc是T&LatLon=>{
返回loc.lat!==未定义和&loc.lon!==未定义;
}
。我发现了两种不同的方法,它们不会产生任何错误(也不依赖于
as
)。一个是我把它分成两个独立的函数,另一个是愚蠢的复杂类型。,这可能是在中提到的编译器错误
通过将LatLon&LatLng
重构为编译器认为与{lng:number;lat:number;lon:number;}
相同的类型,可以说服编译器接受它:
interface LatLonLng extends LatLon, LatLng { }
const fillLonLng1 = <T extends LatLng | LatLon>(loc: T): T & LatLonLng => {
if (isLatLon(loc)) {
return { ...loc, lng: loc.lon };
} else if (isLatLng(loc)) {
return { ...loc, lon: (loc as LatLng).lng };
} else throw new Error();
}
接口LatLonLng扩展LatLon,LatLng{}
常数fillLonLng1=(位置:T):T&LatLonLng=>{
国际单项体育联合会(伊斯拉特隆(loc)){
返回{…loc,lng:loc.lon};
}否则,如果(isLatLng(loc)){
返回{…loc,lon:(loc为LatLng).lng};
}否则抛出新错误();
}
下面的警告仍然有效(即使它们不像我最初认为的那样直接适用这应该是:
interface LatLon {
lat: number;
lon: number;
}
namespace LatLon {
export function is(loc: object): loc is LatLon {
return ['lat', 'lon'].every(key => key in loc && loc[key] !== undefined);
}
}
type LatLng = { lat: number; lng: number; };
export function fillLonLng(loc: LatLng | LatLon): LatLon & LatLng {
return LatLon.is(loc) ? { ...loc, lng: loc.lon } : { ...loc, lon: loc.lng };
}
“isLatLon”的类型是什么?它是一个类型保护函数
const isLatLon=(loc:T):loc是T&LatLon
。我将把它编辑成这个问题。感谢分享您的知识:)我考虑了数字文字的可能性,这就是为什么我提出了省略
版本。但如果这就是问题所在,那么错误信息是错误的,对吗?应该是返回的类型不可分配给T
,而是说它不可分配给LatLon
,它总是这样。嗯,不确定。当我再次接触到一台真正的电脑时,我会看看;它可能更像是验证未指定泛型类型的可分配性的一般限制;编译器不太努力,因为它通常不能正确地完成它,而且这样做通常是一个(有时是微妙的)错误。是的,看看它,我同意你的看法:编译器并没有真正费心在这里验证可分配性。我看你是否能像编译器一样进行重构(LatLonLng
相当于LatLon&LatLng
,但是当与T
相交时,它们的处理方式不同)。我认为这仍然是一个潜在的问题,但我不知道他们是否会考虑这个特定的问题。可能很有趣!我不知道LatLonLng
会受到与工会不同的待遇。
interface LatLonLng extends LatLon, LatLng { }
const fillLonLng1 = <T extends LatLng | LatLon>(loc: T): T & LatLonLng => {
if (isLatLon(loc)) {
return { ...loc, lng: loc.lon };
} else if (isLatLng(loc)) {
return { ...loc, lon: (loc as LatLng).lng };
} else throw new Error();
}
interface LatLon {
lat: number;
lon: number;
}
namespace LatLon {
export function is(loc: object): loc is LatLon {
return ['lat', 'lon'].every(key => key in loc && loc[key] !== undefined);
}
}
type LatLng = { lat: number; lng: number; };
export function fillLonLng(loc: LatLng | LatLon): LatLon & LatLng {
return LatLon.is(loc) ? { ...loc, lng: loc.lon } : { ...loc, lon: loc.lng };
}