Using TypeScript in .cshtml Razor Files

Recently, I embarked on a new project utilizing the ASP.NET-MVC framework. For this particular project, I decided to opt for TypeScript over JavaScript. While Visual Studio provides excellent support for TypeScript, I encountered some compatibility issues when integrating it with .cshtml razor files. Although I could define and utilize classes in my .ts file and call them within the .cshtml file, I faced challenges when passing parameters to objects in the .cshtml file where TypeSafety seemed to be disregarded.

.ts file

export class SomeClass {

    name: number;

    constructor(public tName: number) {
        this.name = tName;
    }

    public sayName() {
        alert(this.name);
    }
}

.cshtml file

var instance = new SomeClass("Timmy");
instance.sayName();

In the above code snippet, I unintentionally passed a string to the constructor despite specifying that only numbers should be accepted as parameters. This caused TypeSafety to be overlooked, leading to the execution of TypeScript/JavaScript without error prompts.

Considering both file types are developed by Microsoft, I found it slightly surprising that they do not seamlessly integrate with each other. Nevertheless, while this issue is not insurmountable and allows me to continue leveraging Object Oriented Programming principles, I am interested to hear from others who may have encountered similar challenges and seek input or insights on this matter.

Answer №1

When using a TypeScript transpiler, it will only check and transpile files that exclusively contain:

  • Javascript code
  • Javascript with additional syntax sugar provided by TypeScript (such as static typing, generic classes, etc.)

CSHTML files are primarily designed to include Razor/C# code along with HTML/JavaScript/CSS elements.

Although some developers try to insert JavaScript code and CSS stylesheets directly into CSHTML files, this is considered a poor practice.

It is recommended to keep JavaScript code and CSS styles in separate files, and then reference them using the script tag for JavaScript or style tag for CSS within your CSHTML file.

Directly embedding JavaScript code in your view (whether it's CSHTML or just HTML) goes against the principles of Unobtrusive JavaScript:

The principle of separating functionality (the "behavior layer") from a Web page's structure/content and presentation (source: Wikipedia)

Some ASP.Net MVC developers persist in placing JavaScript code directly in their Razor views because they need to pass data from the view model to the JavaScript seamlessly. However, this approach is discouraged ;-).

To adhere to Unobtrusive JavaScript principles, all data required by JavaScript should be stored using data attributes within HTML elements:

<span id="mySpan" data-t-name="123456">Hello World</span>

In your TypeScript code, simply utilize jQuery (or vanilla JavaScript) to retrieve the data set in your CSHTML view like so:

let tName: number = parseInt($("#mySpan").data("t-name"));
var instance = new SomeClass(tName);
instance.sayName();

Finally, ensure to reference the generated JavaScript file from TypeScript in your CSHTML file.

I hope this explanation proves helpful!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Getting a "function is not defined" error in Angular 6 while using it within a nested function

I'm facing an issue related to typescript, where the following code is causing trouble: private loadTeams = function(){ let token = sessionStorage.getItem('token'); if(token !== undefined && token !== null && token ...

Webpack focuses solely on serving HTML files, neglecting to deliver the underlying code

Hey there! I'm currently working on a project that involves using React, TypeScript, and Webpack. I ran into some errors previously that prevented the code from compiling, but now that's fixed. However, when I run webpack, it only serves the HTML ...

I am having trouble accessing my JSON data via HTTP get request in Angular 2 when using TypeScript

I am working on developing a JSON file configuration that can be accessed via HTTP GET request in order to retrieve the desired value from the config file and pass it to another component. However, whenever I try to return the value, it shows up as undefin ...

How can I extract a value from an object that is readonly, using a formatted string as the key?

I encountered a situation where I have code resembling the following snippet. It involves an object called errorMessages and multiple fields. Each field corresponds to various error messages in the errorMessages object, but using a formatted string to retr ...

Can the grunt command be executed automatically after saving code in TypeScript?

As a newcomer to FrontEnd and JavaScript coding in TypeScript, I find myself constantly needing to follow these steps after making a code change: save the code -> compile it using Grunt -> reload the webpage. It can be quite time-consuming. Is there a way ...

TimePicker Component for ASP.Net MVC with Razor Syntax

I'm currently working on implementing a TimePicker using Razor and JQueryUI in my bootstrap website. While I have successfully created a DatePicker, I am facing difficulties in creating a separate TimePicker using two different TextBoxes instead of se ...

Why does WebStorm fail to recognize bigint type when using TSC 3.4.x?

Currently, I am working on the models section of my application and considering switching from using number to bigint for id types. However, despite knowing that this is supported from TSC 3.2.x, WebStorm is indicating an error with Unresolved type bigint. ...

Exploring Parquet Files with Node.js

Looking for a solution to read parquet files using NodeJS. Anyone have any suggestions? I attempted to use node-parquet but found it difficult to install and it struggled with reading numerical data types. I also explored parquetjs, however, it can only ...

Troubleshooting Puppeteer compatibility issues when using TypeScript and esModuleInterop

When attempting to use puppeteer with TypeScript and setting esModuleInterop=true in tsconfig.json, an error occurs stating puppeteer.launch is not a function If I try to import puppeteer using import * as puppeteer from "puppeteer" My questi ...

Encountering failures while running Angular tests in GitHub Actions due to reading inner text (which works fine locally)

I am facing an issue in my GitHub actions workflow where Karma is unable to read the 'innerText' of a native element for an Angular project. The error 'TypeError: Cannot read properties of null (reading 'innerText')' is being ...

How can I dynamically insert various FormGroup instances into a FormArray in Angular?

I am looking to dynamically populate the order array with multiple dishes. Each dish will be stored as a FormGroup in the form, such as pizza, salad, drink, or any other type of dish. Prior to adding any items, the form structure should resemble this: this ...

When defining functions in Typescript, the new() syntax is used

Can you explain the purpose of the type declaration for dialogComponent in this specific Typescript code snippet? createDialog(dialogComponent: { new(): DialogComponent }) : Promise<ComponentRef<DialogComponent>> { ... } (Referenced from ...

What is the best way to utilize v-model with an array of strings in a Vuex store when using v-for

Encountered an issue while trying to set a value in an Array within the Vuex Store: VueCompilerError: v-model cannot be used on v-for or v-slot scope variables because they are not writable. Seeking alternatives to achieve this without creating a local co ...

Leverage glob patterns within TypeScript declaration files

Utilizing the file-loader webpack plugin allows for the conversion of media imports into their URLs. For example, in import src from './image.png', the variable src is treated as a string. To inform TypeScript about this behavior, one can create ...

Utilizing the combineReducers() function yields disparate runtime outcomes compared to using a single reducer

Trying to set up a basic store using a root reducer and initial state. The root reducer is as follows: import Entity from "../api/Entity"; import { UPDATE_GROUPING } from "../constants/action-types"; import IAction from "../interfaces/IAction"; import IS ...

What is the reason behind TypeScript indicating that `'string' cannot be assigned to the type 'RequestMode'`?

I'm attempting to utilize the Fetch API in TypeScript, but I keep encountering an issue The error message reads: Type 'string' is not assignable to type 'RequestMode'. Below is the code snippet causing the problem export class ...

Clicking a button in React requires two clicks to update a boolean state by triggering the onClick event

I have a React functional component with input fields, a button, and a tooltip. The tooltip is initially disabled and should only be enabled and visible when the button is clicked and the input fields contain invalid values. The issue I'm facing is t ...

Derive a subset Union from a Union in Typescript

Here is a scenario with a Union type I'm working with; type MyUnionType = 'foo' | 'bar' | 'baz' What I need to do is create a new Union called MySubUnion, which will be a subset of the original; type MySubUnion = &apos ...

Specifying the data structure of a complex nested Map in TypeScript

Struggling to create a deeply nested (recursive) Map in Typescript generically. My attempt is to convert the provided Javascript example to Typescript: const map1 = new Map([ ['key1', 'value1'] ]) const map2 = new Map([ ['keyA& ...

Enhance TypeScript class declarations with additional properties

Our company has developed its own test framework for our software because we found it difficult to use an open-source framework within the context of our specific development needs. Recently, I took on the task of creating Typescript Definition Files to e ...