NSJSONSerialization generating NSCFString* and NSTaggedPointerString*Generating random numbers in Objective-CGenerate JSON string from NSDictionary in iOSHow to use NSJSONSerializationNSJSONSerializationNSJSONSerialization crashing appNSJSONSerialization output number as float?NSJSONSerialization with an integerNSJSONSerialization Returns Error of NULLNSTaggedPointerString objectForKey in objective-cPassing Swift string to and Objective-C framework method causes loss of string

Can I use my US callsign to transmit while in El Salvador?

“The Fourier transform cannot measure two phases at the same frequency.” Why not?

How do people drown while wearing a life jacket?

Why wasn't interlaced CRT scanning done back and forth?

What could prevent players from leaving an island?

How do the surviving Asgardians get to Earth?

How to check a file was encrypted (really & correctly)

Vectorised way to calculate mean of left and right neighbours in a vector

What are the limitations of the Hendersson-Hasselbalch equation?

Why does capacitance not depend on the material of the plates?

A verb for when some rights are not violated?

Why does putting a dot after the URL remove login information?

Piece de Resistance - Introduction & Ace and A's

C# TCP server/client class

Why is the Vasa Museum in Stockholm so Popular?

what can you do with Format View

Write The Shortest Program to Calculate Height of a Binary Tree

Is there a general term for the items in a directory?

What is the right Bonferroni adjustment?

Properties: Left of the colon

Variable doesn't parse as string

Is it uncompelling to continue the story with lower stakes?

Getting Lost in the Caves of Chaos

Broken bottom bracket?



NSJSONSerialization generating NSCFString* and NSTaggedPointerString*


Generating random numbers in Objective-CGenerate JSON string from NSDictionary in iOSHow to use NSJSONSerializationNSJSONSerializationNSJSONSerialization crashing appNSJSONSerialization output number as float?NSJSONSerialization with an integerNSJSONSerialization Returns Error of NULLNSTaggedPointerString objectForKey in objective-cPassing Swift string to and Objective-C framework method causes loss of string






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








17















Executing NSJSONSerialization on the following json sometimes gives me NSCFString* and sometimes NSTaggedPointerString* on string values. Does anyone know why this is the case and what NSJSONSerialization uses to determine which type it returns?



jsonData = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&parseError];


"UserPermissionsService":
"ServiceHeader": ,
"UserApplicationPermissions":
"ApplicationPermissions":
"ApplicationID": "TEST",
"Permission": [

"Locations": [
"00000"
],
"PermissionID": "LOGIN"
,

"Locations": [
"00000"
],
"PermissionID": "SALES_REPORT_VIEW"

]






"LOGIN" comes back as a NSTaggedPointerString*. "SALES_REPORT_VIEW" comes back is a NSCFString*. This is having an impact downstream where I'm using and casting the values.



UPDATE



Here's what I learned...



"NSTaggedPointerString results when the whole value can be kept in the pointer itself without allocating any data."



There's a detailed explanation here...



https://www.mikeash.com/pyblog/friday-qa-2015-07-31-tagged-pointer-strings.html



Since NSTaggedPointerString is a subclass of NSString showing quotes / not showing quotes should never been an issue for me as the data is used.



Thanks for everyone that commented. I'm comfortable I understand what NSJSONSerialization is doing.










share|improve this question





















  • 1





    What are you doing that it makes a difference? You always get an NSString*. Which subclass of NSString* shouldn't ever matter to you.

    – gnasher729
    Oct 13 '15 at 14:59






  • 2





    Google for NSTaggedPointerString. If this makes a difference to you then you are doing something very, very wrong. Tagged pointers are very common on 64 bit systems for small values where the whole value can be kept in the pointer itself without allocating any data.

    – gnasher729
    Oct 13 '15 at 15:00







  • 1





    @Justin Domnitz I don't believe you are on the right track here, please add an example of how you use the values or their types.

    – A-Live
    Oct 13 '15 at 15:58






  • 1





    I think we've gone a little off track here. :) I'm really just trying to understand the results I'm getting from NSJSONSerialization. The best answer seems to be from gnasher729 with regard to the system determining that "NSTaggedPointerString results when the whole value can be kept in the pointer itself without allocating any data". Can anyone point me to the documentation on this? Google is not yielding anything useful (which is why I posted the question here).

    – Justin Domnitz
    Oct 13 '15 at 18:03






  • 3





    Lol @gnasher729 someone comes to stackoverflow with a question but receives more questions instead, great... Also, Justin if you found an answer please create one and mark yours as answered. For example, I have problems when NSJSONSerialization messes up dictionary keys as NSTaggedPointerStrings and can no longer access those values unless they are cast explicitly which makes for nasty looking indexing

    – Michael Lorenzo
    Apr 7 '16 at 20:56

















17















Executing NSJSONSerialization on the following json sometimes gives me NSCFString* and sometimes NSTaggedPointerString* on string values. Does anyone know why this is the case and what NSJSONSerialization uses to determine which type it returns?



jsonData = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&parseError];


"UserPermissionsService":
"ServiceHeader": ,
"UserApplicationPermissions":
"ApplicationPermissions":
"ApplicationID": "TEST",
"Permission": [

"Locations": [
"00000"
],
"PermissionID": "LOGIN"
,

"Locations": [
"00000"
],
"PermissionID": "SALES_REPORT_VIEW"

]






"LOGIN" comes back as a NSTaggedPointerString*. "SALES_REPORT_VIEW" comes back is a NSCFString*. This is having an impact downstream where I'm using and casting the values.



UPDATE



Here's what I learned...



"NSTaggedPointerString results when the whole value can be kept in the pointer itself without allocating any data."



There's a detailed explanation here...



https://www.mikeash.com/pyblog/friday-qa-2015-07-31-tagged-pointer-strings.html



Since NSTaggedPointerString is a subclass of NSString showing quotes / not showing quotes should never been an issue for me as the data is used.



Thanks for everyone that commented. I'm comfortable I understand what NSJSONSerialization is doing.










share|improve this question





















  • 1





    What are you doing that it makes a difference? You always get an NSString*. Which subclass of NSString* shouldn't ever matter to you.

    – gnasher729
    Oct 13 '15 at 14:59






  • 2





    Google for NSTaggedPointerString. If this makes a difference to you then you are doing something very, very wrong. Tagged pointers are very common on 64 bit systems for small values where the whole value can be kept in the pointer itself without allocating any data.

    – gnasher729
    Oct 13 '15 at 15:00







  • 1





    @Justin Domnitz I don't believe you are on the right track here, please add an example of how you use the values or their types.

    – A-Live
    Oct 13 '15 at 15:58






  • 1





    I think we've gone a little off track here. :) I'm really just trying to understand the results I'm getting from NSJSONSerialization. The best answer seems to be from gnasher729 with regard to the system determining that "NSTaggedPointerString results when the whole value can be kept in the pointer itself without allocating any data". Can anyone point me to the documentation on this? Google is not yielding anything useful (which is why I posted the question here).

    – Justin Domnitz
    Oct 13 '15 at 18:03






  • 3





    Lol @gnasher729 someone comes to stackoverflow with a question but receives more questions instead, great... Also, Justin if you found an answer please create one and mark yours as answered. For example, I have problems when NSJSONSerialization messes up dictionary keys as NSTaggedPointerStrings and can no longer access those values unless they are cast explicitly which makes for nasty looking indexing

    – Michael Lorenzo
    Apr 7 '16 at 20:56













17












17








17








Executing NSJSONSerialization on the following json sometimes gives me NSCFString* and sometimes NSTaggedPointerString* on string values. Does anyone know why this is the case and what NSJSONSerialization uses to determine which type it returns?



jsonData = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&parseError];


"UserPermissionsService":
"ServiceHeader": ,
"UserApplicationPermissions":
"ApplicationPermissions":
"ApplicationID": "TEST",
"Permission": [

"Locations": [
"00000"
],
"PermissionID": "LOGIN"
,

"Locations": [
"00000"
],
"PermissionID": "SALES_REPORT_VIEW"

]






"LOGIN" comes back as a NSTaggedPointerString*. "SALES_REPORT_VIEW" comes back is a NSCFString*. This is having an impact downstream where I'm using and casting the values.



UPDATE



Here's what I learned...



"NSTaggedPointerString results when the whole value can be kept in the pointer itself without allocating any data."



There's a detailed explanation here...



https://www.mikeash.com/pyblog/friday-qa-2015-07-31-tagged-pointer-strings.html



Since NSTaggedPointerString is a subclass of NSString showing quotes / not showing quotes should never been an issue for me as the data is used.



Thanks for everyone that commented. I'm comfortable I understand what NSJSONSerialization is doing.










share|improve this question
















Executing NSJSONSerialization on the following json sometimes gives me NSCFString* and sometimes NSTaggedPointerString* on string values. Does anyone know why this is the case and what NSJSONSerialization uses to determine which type it returns?



jsonData = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&parseError];


"UserPermissionsService":
"ServiceHeader": ,
"UserApplicationPermissions":
"ApplicationPermissions":
"ApplicationID": "TEST",
"Permission": [

"Locations": [
"00000"
],
"PermissionID": "LOGIN"
,

"Locations": [
"00000"
],
"PermissionID": "SALES_REPORT_VIEW"

]






"LOGIN" comes back as a NSTaggedPointerString*. "SALES_REPORT_VIEW" comes back is a NSCFString*. This is having an impact downstream where I'm using and casting the values.



UPDATE



Here's what I learned...



"NSTaggedPointerString results when the whole value can be kept in the pointer itself without allocating any data."



There's a detailed explanation here...



https://www.mikeash.com/pyblog/friday-qa-2015-07-31-tagged-pointer-strings.html



Since NSTaggedPointerString is a subclass of NSString showing quotes / not showing quotes should never been an issue for me as the data is used.



Thanks for everyone that commented. I'm comfortable I understand what NSJSONSerialization is doing.







objective-c json nsstring foundation nsjsonserialization






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 9 '18 at 14:36









ayaio

60.7k20 gold badges136 silver badges199 bronze badges




60.7k20 gold badges136 silver badges199 bronze badges










asked Oct 13 '15 at 14:47









Justin DomnitzJustin Domnitz

2,10619 silver badges28 bronze badges




2,10619 silver badges28 bronze badges










  • 1





    What are you doing that it makes a difference? You always get an NSString*. Which subclass of NSString* shouldn't ever matter to you.

    – gnasher729
    Oct 13 '15 at 14:59






  • 2





    Google for NSTaggedPointerString. If this makes a difference to you then you are doing something very, very wrong. Tagged pointers are very common on 64 bit systems for small values where the whole value can be kept in the pointer itself without allocating any data.

    – gnasher729
    Oct 13 '15 at 15:00







  • 1





    @Justin Domnitz I don't believe you are on the right track here, please add an example of how you use the values or their types.

    – A-Live
    Oct 13 '15 at 15:58






  • 1





    I think we've gone a little off track here. :) I'm really just trying to understand the results I'm getting from NSJSONSerialization. The best answer seems to be from gnasher729 with regard to the system determining that "NSTaggedPointerString results when the whole value can be kept in the pointer itself without allocating any data". Can anyone point me to the documentation on this? Google is not yielding anything useful (which is why I posted the question here).

    – Justin Domnitz
    Oct 13 '15 at 18:03






  • 3





    Lol @gnasher729 someone comes to stackoverflow with a question but receives more questions instead, great... Also, Justin if you found an answer please create one and mark yours as answered. For example, I have problems when NSJSONSerialization messes up dictionary keys as NSTaggedPointerStrings and can no longer access those values unless they are cast explicitly which makes for nasty looking indexing

    – Michael Lorenzo
    Apr 7 '16 at 20:56












  • 1





    What are you doing that it makes a difference? You always get an NSString*. Which subclass of NSString* shouldn't ever matter to you.

    – gnasher729
    Oct 13 '15 at 14:59






  • 2





    Google for NSTaggedPointerString. If this makes a difference to you then you are doing something very, very wrong. Tagged pointers are very common on 64 bit systems for small values where the whole value can be kept in the pointer itself without allocating any data.

    – gnasher729
    Oct 13 '15 at 15:00







  • 1





    @Justin Domnitz I don't believe you are on the right track here, please add an example of how you use the values or their types.

    – A-Live
    Oct 13 '15 at 15:58






  • 1





    I think we've gone a little off track here. :) I'm really just trying to understand the results I'm getting from NSJSONSerialization. The best answer seems to be from gnasher729 with regard to the system determining that "NSTaggedPointerString results when the whole value can be kept in the pointer itself without allocating any data". Can anyone point me to the documentation on this? Google is not yielding anything useful (which is why I posted the question here).

    – Justin Domnitz
    Oct 13 '15 at 18:03






  • 3





    Lol @gnasher729 someone comes to stackoverflow with a question but receives more questions instead, great... Also, Justin if you found an answer please create one and mark yours as answered. For example, I have problems when NSJSONSerialization messes up dictionary keys as NSTaggedPointerStrings and can no longer access those values unless they are cast explicitly which makes for nasty looking indexing

    – Michael Lorenzo
    Apr 7 '16 at 20:56







1




1





What are you doing that it makes a difference? You always get an NSString*. Which subclass of NSString* shouldn't ever matter to you.

– gnasher729
Oct 13 '15 at 14:59





What are you doing that it makes a difference? You always get an NSString*. Which subclass of NSString* shouldn't ever matter to you.

– gnasher729
Oct 13 '15 at 14:59




2




2





Google for NSTaggedPointerString. If this makes a difference to you then you are doing something very, very wrong. Tagged pointers are very common on 64 bit systems for small values where the whole value can be kept in the pointer itself without allocating any data.

– gnasher729
Oct 13 '15 at 15:00






Google for NSTaggedPointerString. If this makes a difference to you then you are doing something very, very wrong. Tagged pointers are very common on 64 bit systems for small values where the whole value can be kept in the pointer itself without allocating any data.

– gnasher729
Oct 13 '15 at 15:00





1




1





@Justin Domnitz I don't believe you are on the right track here, please add an example of how you use the values or their types.

– A-Live
Oct 13 '15 at 15:58





@Justin Domnitz I don't believe you are on the right track here, please add an example of how you use the values or their types.

– A-Live
Oct 13 '15 at 15:58




1




1





I think we've gone a little off track here. :) I'm really just trying to understand the results I'm getting from NSJSONSerialization. The best answer seems to be from gnasher729 with regard to the system determining that "NSTaggedPointerString results when the whole value can be kept in the pointer itself without allocating any data". Can anyone point me to the documentation on this? Google is not yielding anything useful (which is why I posted the question here).

– Justin Domnitz
Oct 13 '15 at 18:03





I think we've gone a little off track here. :) I'm really just trying to understand the results I'm getting from NSJSONSerialization. The best answer seems to be from gnasher729 with regard to the system determining that "NSTaggedPointerString results when the whole value can be kept in the pointer itself without allocating any data". Can anyone point me to the documentation on this? Google is not yielding anything useful (which is why I posted the question here).

– Justin Domnitz
Oct 13 '15 at 18:03




3




3





Lol @gnasher729 someone comes to stackoverflow with a question but receives more questions instead, great... Also, Justin if you found an answer please create one and mark yours as answered. For example, I have problems when NSJSONSerialization messes up dictionary keys as NSTaggedPointerStrings and can no longer access those values unless they are cast explicitly which makes for nasty looking indexing

– Michael Lorenzo
Apr 7 '16 at 20:56





Lol @gnasher729 someone comes to stackoverflow with a question but receives more questions instead, great... Also, Justin if you found an answer please create one and mark yours as answered. For example, I have problems when NSJSONSerialization messes up dictionary keys as NSTaggedPointerStrings and can no longer access those values unless they are cast explicitly which makes for nasty looking indexing

– Michael Lorenzo
Apr 7 '16 at 20:56












2 Answers
2






active

oldest

votes


















1














Much of Foundation is implemented as class clusters. TL;DR you interact with it as an NSString but foundation will change the backing implementation to optimize for certain performance or space characteristics based on the actual contents.



If you are curious one of the Foundation team dumped a list of the class clusters as of iOS 11 here






share|improve this answer
































    0














    I FIXED IT BY USING "MUTABLECOPY"



    I had the same issue. For some "performance" mechanism apparently apple uses NSTaggedPointerString for "well known" strings such as "California" but this might be an issue since for some weird reason the NSJSONSerialization doesn't add the quotes around this NSTaggedPointerString type of strings. The work around is simple:



    NSString *taggedString = @"California";
    [data setObject:[taggedString mutableCopy] forKey:@"state"]


    Works like a charm.






    share|improve this answer



























      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f33105750%2fnsjsonserialization-generating-nscfstring-and-nstaggedpointerstring%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      1














      Much of Foundation is implemented as class clusters. TL;DR you interact with it as an NSString but foundation will change the backing implementation to optimize for certain performance or space characteristics based on the actual contents.



      If you are curious one of the Foundation team dumped a list of the class clusters as of iOS 11 here






      share|improve this answer





























        1














        Much of Foundation is implemented as class clusters. TL;DR you interact with it as an NSString but foundation will change the backing implementation to optimize for certain performance or space characteristics based on the actual contents.



        If you are curious one of the Foundation team dumped a list of the class clusters as of iOS 11 here






        share|improve this answer



























          1












          1








          1







          Much of Foundation is implemented as class clusters. TL;DR you interact with it as an NSString but foundation will change the backing implementation to optimize for certain performance or space characteristics based on the actual contents.



          If you are curious one of the Foundation team dumped a list of the class clusters as of iOS 11 here






          share|improve this answer













          Much of Foundation is implemented as class clusters. TL;DR you interact with it as an NSString but foundation will change the backing implementation to optimize for certain performance or space characteristics based on the actual contents.



          If you are curious one of the Foundation team dumped a list of the class clusters as of iOS 11 here







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jan 9 '18 at 14:35









          tapitapi

          1,6561 gold badge16 silver badges16 bronze badges




          1,6561 gold badge16 silver badges16 bronze badges


























              0














              I FIXED IT BY USING "MUTABLECOPY"



              I had the same issue. For some "performance" mechanism apparently apple uses NSTaggedPointerString for "well known" strings such as "California" but this might be an issue since for some weird reason the NSJSONSerialization doesn't add the quotes around this NSTaggedPointerString type of strings. The work around is simple:



              NSString *taggedString = @"California";
              [data setObject:[taggedString mutableCopy] forKey:@"state"]


              Works like a charm.






              share|improve this answer





























                0














                I FIXED IT BY USING "MUTABLECOPY"



                I had the same issue. For some "performance" mechanism apparently apple uses NSTaggedPointerString for "well known" strings such as "California" but this might be an issue since for some weird reason the NSJSONSerialization doesn't add the quotes around this NSTaggedPointerString type of strings. The work around is simple:



                NSString *taggedString = @"California";
                [data setObject:[taggedString mutableCopy] forKey:@"state"]


                Works like a charm.






                share|improve this answer



























                  0












                  0








                  0







                  I FIXED IT BY USING "MUTABLECOPY"



                  I had the same issue. For some "performance" mechanism apparently apple uses NSTaggedPointerString for "well known" strings such as "California" but this might be an issue since for some weird reason the NSJSONSerialization doesn't add the quotes around this NSTaggedPointerString type of strings. The work around is simple:



                  NSString *taggedString = @"California";
                  [data setObject:[taggedString mutableCopy] forKey:@"state"]


                  Works like a charm.






                  share|improve this answer













                  I FIXED IT BY USING "MUTABLECOPY"



                  I had the same issue. For some "performance" mechanism apparently apple uses NSTaggedPointerString for "well known" strings such as "California" but this might be an issue since for some weird reason the NSJSONSerialization doesn't add the quotes around this NSTaggedPointerString type of strings. The work around is simple:



                  NSString *taggedString = @"California";
                  [data setObject:[taggedString mutableCopy] forKey:@"state"]


                  Works like a charm.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Mar 27 at 2:47









                  user2387149user2387149

                  90713 silver badges28 bronze badges




                  90713 silver badges28 bronze badges






























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f33105750%2fnsjsonserialization-generating-nscfstring-and-nstaggedpointerstring%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

                      Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

                      Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript