How to hint to typescript that a string is consistent across multiple indexing operations

Minimal example of the problem:


const a = {
    'x': {},
    'y': 'y',
};
const b = {
    'x': {},
    'y': 'y',
};
for (const p of ['x', 'y'] as const) {
    a[p] = b[p]; // error string | {} is not assignable to {} & string
}
for (const p of ['x', 'y'] as const) {
    switch (p) {
        case 'x':
            a[p] = b[p]; // no error
            break;
        case 'y':
            a[p] = b[p]; // no error
            break;
    }
}

Typescript sees the type of p as 'x' | 'y' but doesn’t correlate the fact that a and b are being indexed by the same value.

Is there a way to… distribute? the union operation so that essentially the typed expression becomes goes from a['x'|'y'] = b['x'|'y'] to a['x'] = b['x'] | a['y'] = b['y']

I’ve tried generic functions and a host of attempts at coercing the types of the inputs but short of asserting as any nothing seems to work.

I’d like to avoid type as assertions (especially to any) as it adds one more area where type analysis is likely to fail, but I feel like I don’t have any other options other than generating code during build but that’s a rather large additional build step I’d rather not add for something that feels small like this.

A switch statement isn’t a feasible alternative since the actual number of keys is much larger than 2 and is liable to change so this would involve adding many sections of duplicated code throughout my codebase.

This is a consequence of a type safety improvement to indexed access types introduced in TypeScript 3.5, as implemented by microsoft/TypeScript#30769. In general it is unsafe to allow a[p] = b[q] where a and b are of the same object type and where p and q are of the same union type, since if p and q turn out to be different elements of the union, you might be writing an incompatible value. In your case you are doing a[p] = b[p], but from the type system’s perspective that’s the same thing; all it sees is that you are writing and reading an object property whose key is a union type "x" | "y", which is unsafe in general. It doesn’t pay attention to the fact that if you’re using the exact same value p in both places, then it has to be safe.

So since TypeScript 3.5 this has been a pain point. There is a request to fix this for when you are reading or writing the “same” property; see microsoft/TypeScript#32693. And, fortunately, according to this comment it looks like this will be fixed for the case here where you’re literally using the same identifier (like p) as the key. Not sure when that will happen, though… the issue seems to be on the Backlog and not slated for a particular release of TypeScript. So it could be a while.


Until then it should be possible to refactor to a generic function, since one place they still allow the older pre-TS-3.5 unsafe access is when you are using generic type. This is mentioned in a comment on #30769:

One rule we’ve always had is that any given type (and, by extension, any T[K] for identical T and K) is by definition assignable to itself, and that’s the basic unsoundness we permit

So if we introduce this indirection:

function copyProp<T, K extends keyof T>(dst: T, src: T, key: K) {
    dst[key] = src[key];
}

That compiles just fine, and now we can use it:

for (const p of ['x', 'y'] as const) {
    copyProp(a, b, p);
}

which also compiles without error. It’s annoying, but at least there is a solution/workaround that works for now, at least until a fix for #32693 is released.


One last thought about wishing this could be fixed in general so you could avoid switch statements. A while ago I opened a feature request microsoft/TypeScript#25051 to allow for “opt-in distributive control flow analysis” where you could say something like type switch (p) {...} and have the compiler evaluate the enclosed code block once for each element of the union type of p, and if each pass succeeded, then the whole thing would succeed. The compiler feasibly can’t do that kind of multi-pass analysis for each union-typed expression it encounters, but I was hoping we could at least have some syntax to ask for it in specific cases. Alas, it is not to be (and was closed as a duplicate of one of the several issues it would address), but when I see this issue I become wistful and think of what might have been…. Sigh…


Okay, hope that helps; good luck!

Playground link to code

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật