Skip to content

How to use nullable reference type information with generic types. #295

@juliusfriedman

Description

@juliusfriedman

Hello, @pavel-b-novikov and team.

My issue is very similar to this issue

I define some server model like this:

[TsInterface]
public class GenericValue<T>
{
    public int Key { get; set; }

    public T? Value { get; set; }
}

It is properly defined in TypeScipt as follows

export interface GenericValue<T>
{
  Key: number;
  Value?: T;
}

I use it like so (From C#)

public class DTO
{
    public GenericValue<string?> SomeProperty { get; set; } = null!
}

I would expect the TypeScript to be written as:

export inteface DTO
{
    SomeProperty: IGenericValue<string | undefined>;
}

instead it is written in TypeScript as

export inteface DTO
{
    SomeProperty: IGenericValue<string>;
}

I do not believe this is in agreement with the nullable annotation in the type.

I think the problem is that RtSimpleTypeName does not retain the information on if the type was nullable when its constructed, as a result the code which outputs the generic type information into the AST does not have a way to determine the nullability.

See here, it seems the ToString method is called and it missed already the ability to pass the NRT information to the constructed RtSimpleTypeName.

I don't think I can implement this using my own Visitor because of how SerializeGenericArguments is called, there is no way to determine if the type was nullable or not?

This is evident by looking at the ToString method of RtSimpleName

Here is a naive implementation which shows what I am trying to do but only WRT to nullability which I can't seem to do without changing things around in the library.

public sealed class NRTTypeScriptExportVisitor(
    TextWriter writer,
    ExportContext exportContext)
    : TypeScriptExportVisitor(writer, exportContext)
{
public override void Visit(RtSimpleTypeName node)
{
    if (node.HasPrefix)
    {
        Write(node.Prefix);
        Write(".");
    }

    Write(node.TypeName);

    if (node.GenericArguments.Length != 0)
    {
        Write("<");
        for (var i = 0; i < node.GenericArguments.Length; ++i)
        {
            var genericArgument = node.GenericArguments[i];

            Visit(genericArgument);

            Write(" | undefined"); //I only want to output this if genericArgument.Identifier.IsNullable but there is no way to access that information here

            if (i < node.GenericArguments.Length - 1)
                Write(", ");
        }
        Write(">");
    }
}
}

Am I missing something?

I think I could commit a simple fix for this issue by retaining the nullable type information when constructing the RtSimpleName in the code but I need to understand first if I am doing anything incorrectly WRT to my visitor.

Thank you in advance for your assistance with this matter!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions