0

In my Razor .cshtml file I need to pass a JSON-serialized data from some complex C# POCO model objects that can be used in the Javascript space. But I want to use type-safe Typescript instead, which VS 2017/2019 now has great support (by auto-transpile during the build). That way I can also use ES6 features.

I am looking for tips on generating typescript .d files so the typescript scripts I use has the benefit of type checking when operating on the JSON data derived from the C# POCO model.

There is an SO answer recommending Web Essentials but it has not been updated for VS 2017/2019, and I suspect now that VS 2017/2019 has Roslyn built-in and support Typescript a lot more than VS 2015, I'm hoping it has a way to do this without installing any extensions or requiring any nuget libraries.

I can settle for manually generating it (maybe by right-clicking on the POCO root class from the Solution Explorer tab inside the VS 2017/2019 IDE). But what is even better if the generation of the .d files are automatic so that whenever the C# POCO class is updated, the syntax helper in the .ts editing window is updated automatically. I'm hoping that the integrated Rosyln feature somehow makes it work like magic :-).

GratefulDisciple
  • 674
  • 8
  • 18
  • 1
    https://frhagn.github.io/Typewriter/ –  Dec 05 '19 at 19:22
  • @Amy Thanks. I prefer a native VS2017/2019 solution, but will consider [Typewriter](https://frhagn.github.io/Typewriter/) as a fallback. I also found [TypeScript Definition Generator](https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TypeScriptDefinitionGenerator). – GratefulDisciple Dec 05 '19 at 19:29
  • I've been using Typewriter for the past couple of years and absolutely love it. Cheers. –  Dec 05 '19 at 19:30

2 Answers2

0

Since POCO objects often represent tables, I have my solution to create classes based on SQL table in MS SQL Management Studio.

First create this stored proc:

CREATE PROC [dbo].[CreateClass](
    @Schema VARCHAR(100),
    @TableName VARCHAR(100),
    @Type VARCHAR(2) = NULL

)
AS
IF @Type IS NULL
    SET @Type = 'T'

SET NOCOUNT ON
DECLARE @TableInfo TABLE (
    ColumnName VARCHAR(100),
    ColumnPosition INT,
    ColumnTypeCS VARCHAR(100),
    ColumnTypeTS VARCHAR(100),
    NullableSign CHAR(1)
)

INSERT INTO @TableInfo
    SELECT 
        replace(COLUMN_NAME, ' ', '_') ,
        ORDINAL_POSITION AS ColumnPosition,
        CASE DATA_TYPE
            WHEN 'bigint' THEN 'long'
            WHEN 'binary' THEN 'byte[]'
            WHEN 'bit' THEN 'bool'
            WHEN 'char' THEN 'string'
            WHEN 'date' THEN 'DateTime'
            WHEN 'datetime' THEN 'DateTime'
            WHEN 'datetime2' THEN 'DateTime'
            WHEN 'datetimeoffset' THEN 'DateTimeOffset'
            WHEN 'decimal' THEN 'decimal'
            WHEN 'float' THEN 'double'
            WHEN 'image' THEN 'byte[]'
            WHEN 'int' THEN 'int'
            WHEN 'money' THEN 'decimal'
            WHEN 'nchar' THEN 'string'
            WHEN 'ntext' THEN 'string'
            WHEN 'numeric' THEN 'decimal'
            WHEN 'nvarchar' THEN 'string'
            WHEN 'real' THEN 'double'
            WHEN 'smalldatetime' THEN 'DateTime'
            WHEN 'smallint' THEN 'short'
            WHEN 'smallmoney' THEN 'decimal'
            WHEN 'text' THEN 'string'
            WHEN 'time' THEN 'TimeSpan'
            WHEN 'timestamp' THEN 'DateTime'
            WHEN 'tinyint' THEN 'byte'
            WHEN 'uniqueidentifier' THEN 'Guid'
            WHEN 'varbinary' THEN 'byte[]'
            WHEN 'varchar' THEN 'string'
            ELSE 'UNKNOWN_' + DATA_TYPE
        END AS ColumnTypeCS,
        CASE DATA_TYPE
            WHEN 'bigint' THEN 'number'
            WHEN 'binary' THEN 'any'
            WHEN 'bit' THEN 'boolean'
            WHEN 'char' THEN 'string'
            WHEN 'date' THEN 'Date'
            WHEN 'datetime' THEN 'Date'
            WHEN 'datetime2' THEN 'Date'
            WHEN 'datetimeoffset' THEN 'Date'
            WHEN 'decimal' THEN 'number'
            WHEN 'float' THEN 'number'
            WHEN 'image' THEN 'any'
            WHEN 'int' THEN 'number'
            WHEN 'money' THEN 'number'
            WHEN 'nchar' THEN 'string'
            WHEN 'ntext' THEN 'string'
            WHEN 'numeric' THEN 'number'
            WHEN 'nvarchar' THEN 'string'
            WHEN 'real' THEN 'number'
            WHEN 'smalldatetime' THEN 'Date'
            WHEN 'smallint' THEN 'number'
            WHEN 'smallmoney' THEN 'number'
            WHEN 'text' THEN 'string'
            WHEN 'time' THEN 'number'
            WHEN 'timestamp' THEN 'number'
            WHEN 'tinyint' THEN 'number'
            WHEN 'uniqueidentifier' THEN 'string'
            WHEN 'varbinary' THEN 'any'
            WHEN 'varchar' THEN 'string'
            ELSE 'UNKNOWN_' + DATA_TYPE
        END ColumnTypeTS,
        CASE 
            WHEN IS_NULLABLE = 'YES' and DATA_TYPE in ('bigint', 'bit', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'time', 'tinyint', 'uniqueidentifier') 
            THEN '?' 
            ELSE '' 
        END NullableSign
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = @TableName AND TABLE_SCHEMA = @Schema 


DECLARE @Result VARCHAR(MAX) = 'public class ' + @TableName + '
{'

SELECT @Result = @Result + '
    public ' + ColumnTypeCS + NullableSign + ' ' + ColumnName + ' { get; set; }
'
FROM @TableInfo
ORDER BY ColumnPosition

SET @Result = @Result  + '
}'

IF CHARINDEX('C', @Type) > 0
    PRINT @Result


UPDATE @TableInfo
    SET ColumnName = LOWER(SUBSTRING(ColumnName, 1, 1)) + SUBSTRING(ColumnName, 2, LEN(ColumnName))

SET @Result = '
export interface I' + @TableName + '
{'

SELECT @Result = @Result + '
    '+ColumnName + '?: ' + ColumnTypeTS + ';'
FROM @TableInfo
ORDER BY ColumnPosition

SET @Result = @Result  + '
}
'

IF CHARINDEX('T', @Type) > 0
    PRINT @Result


SET @Result = '
export class ' + @TableName + ' implements I'+@TableName+'
{'

SELECT @Result = @Result + '
    '+ColumnName + '?: ' + ColumnTypeTS + ';'
FROM @TableInfo
ORDER BY ColumnPosition

SET @Result = @Result  + '

    constructor(recoverFrom: '+@TableName+' | I'+@TableName+') {
        super(recoverFrom);
    }
}
'
PRINT @Result
GO

to use, simply execute this

EXEC dbo.CreateClass @Schema = 'dbo', @TableName = 'MyTable', @Type = 'T'
or
EXEC dbo.CreateClass @Schema = 'dbo', @TableName = 'MyTable', @Type = 'C'
or
EXEC dbo.CreateClass @Schema = 'dbo', @TableName = 'MyTable'

and see the result in C#, Typescript or both

tgralex
  • 794
  • 4
  • 14
  • I appreciate your answer, but it's too heavy, involving SQL, etc. I highly recommend a VS Studio extension [TypeScript Definition Generator](https://github.com/madskristensen/TypeScriptDefinitionGenerator/) which have been working great for me in the past few months. – GratefulDisciple Mar 18 '20 at 14:28
0

TypeScript Definition Generator, a Visual Studio Extension, has been working very well for the past few months. It works for the latest Visual Studio 2019 update as well (as of version 16.4.6).

Once installed you can designate the POCO .cs file that you want a .ts.d file auto generated for you simply by right clicking on it in Solution Explorer. From then on, everytime you update that POCO .cs file, the associated .ts.d file is automatically updated.

In my usage I put several POCO into one .cs file so I only have to right click on a few files for the dozens of POCO that I need.

GratefulDisciple
  • 674
  • 8
  • 18