简体   繁体   中英

String or Number values in Typescript

An example of what I am trying to achieve:

class Test {
    private _folderId: number;
    private _pageId: number;
    private _folderName: string;
    private _pageName: string;

    constructor(pageId: string | number, folderId: string | number){
        this._folderId = (!isNaN(+folderId)) ? folderId : undefined;
        this._pageId = (!isNaN(+pageId)) ? pageId : undefined;
        this._folderName = (isNaN(+folderId)) ? folderId : undefined;
        this._pageName = (isNaN(+pageId)) ? pageId : undefined;
    }
}

Unfortunately this throws compiler error:

TS2322:Type 'string | number' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'.

and so on (similar error for each var).

Is there any way around it? At the moment only thing I can do is to set page and folder id to type any...

You should use the typeof operator like

typeof folderId === "number"

to check for number or string.

The comment under the Guenter Guckelsberger's answer suggests you need to use strings like '123' as numbers. Here is a solution:

/**
* See http://stackoverflow.com/questions/9716468/is-there-any-function-like-isnumeric-in-javascript-to-validate-numbers
*/
function isNumeric(n: any) : n is number | string {
    return !isNaN(parseFloat(n)) && isFinite(n);
}

function intVal(n: number | string): number {
    return typeof n === "number" ? n : parseInt(n, 10);
}

class Test {
    private _folderId: number;
    private _pageId: number;
    private _folderName: string;
    private _pageName: string;

    constructor(pageId: string | number, folderId: string | number) {
        if (isNumeric(folderId))
            this._folderId = intVal(folderId);
        else
            this._folderName = <string>folderId;
        if (isNumeric(pageId))
            this._pageId = intVal(pageId);
        else
            this._pageName = <string>pageId;
    }
}

Since you have mentioned an ambiguous type for pageId and folderId typescript cannot make out whether your variable is a number or a string at the time of assignment. Hence you need to specify the exact type of your variable at the time of assignment. This can be done using typecasting

You can typecast your folderId and pageId to number or string as follows:

constructor(pageId: string | number, folderId: string | number){
    this._folderId = (!isNaN(+folderId)) ? folderId as number : undefined;
    this._pageId = (!isNaN(+pageId)) ? pageId as number : undefined;
    this._folderName = (isNaN(+folderId)) ? folderId as string : undefined;
    this._pageName = (isNaN(+pageId)) ? pageId as string: undefined;
}

Another way of typecasting would be <number>folderId <string>folderId . You can also go for type Guards as shown in 'Paleo's answer

For people, like me, who came here looking for a way to constrain a type to strings which can be evaluated to numbers, you can use template literal types. There is a typescript playground with the following:

type SoN = `${number}`
const pass1 = '1'
const pass2 = '-1'
const pass3 = '1.0'
const pass4 = '3e44'
const fail1 = 'abc'
const fail2 = 'NaN'

function sumStrings(str1: SoN, str2: SoN, str3: SoN, str4: SoN, str5: SoN, str6: SoN) {
    return str1 + str2 + str3 + str4 + str5 + str6 // LOL
}

sumStrings(
    pass1,
    pass2,
    pass3,
    pass4,
    fail1,
    fail2
)

There is some discussion of this in the Typescript github issues :

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM