fable-compiler / Fable

F# to JavaScript, TypeScript, Python, Rust and Dart Compiler
http://fable.io/
MIT License
2.92k stars 300 forks source link

[TypeScript] IDictionary and IReadOnlyDictionary interfaces #3665

Open leononame opened 11 months ago

leononame commented 11 months ago

Description

I understand it's not part of the F# core library and isn't covered in the docs either, but IReadOnlyDictionary and IDictionary are abstractions around types that are covered by Fale (Dictionary and Map) and are well integrated with F# using dict and readOnlyDict. In TypeScript, the types compile to any, which makes it impossible to use it under certain circumstances.

Repro code

open System.Collections.Generic

type T = {A: int }
// Write code or load a sample from sidebar
let dict = [(1,{A=1});(2,{A=1});(3,{A=1})] |> readOnlyDict
let getValue (dict: IReadOnlyDictionary<int, T>) value = 
    dict[value].A

let value = getValue dict 1

results in this TypeScript code:

import { Record } from "fable-library/Types.js";
import { int32 } from "fable-library/Int32.js";
import { IComparable, IEquatable } from "fable-library/Util.js";
import { record_type, int32_type, TypeInfo } from "fable-library/Reflection.js";
import { getItemFromDict } from "fable-library/MapUtil.js";

export class T extends Record implements IEquatable<T>, IComparable<T> {
    readonly A: int32;
    constructor(A: int32) {
        super();
        this.A = (A | 0);
    }
}

export function T_$reflection(): TypeInfo {
    return record_type("Test.T", [], T, () => [["A", int32_type]]);
}

export const dict: any = new Map<int32, T>([[1, new T(1)] as [int32, T], [2, new T(1)] as [int32, T], [3, new T(1)] as [int32, T]]);

export function getValue(dict_1: any, value_1: int32): int32 {
    return getItemFromDict(dict_1, value_1).A;
}

export const value: int32 = getValue(dict, 1);

However, return getItemFromDict(dict_1, value_1).A; is an error in TypeScript (TS2571: Object is of type unknown). I understand that IDictionary is more complicated because it has a bigger surface, but compiling IReadOnlyDicitionary to something similar to what IMap is in TypeScript should be possible, right?

dbrattli commented 11 months ago

Thanks for opening this issue. I think this should be possible. We have those interfaces for Python (almost) so should be possible for TypeScript as well. Let me have a look ...

leononame commented 10 months ago

@dbrattli Hi, sorry for bothering again. Did you have any success, it's kind of a blocking issue for me at the moment. I'd be happy to help out as well if I can, but maybe you could give me a pointer on where to start?