类型String和string有什么区别?

524

有人知道 TypeScript 中 Stringstring 之间的区别吗?我认为它们应该是相同的,我的想法正确吗?

有人知道 TypeScript 中 Stringstring 之间的区别吗?我认为它们应该是相同的,我的想法正确吗?

var a: String = "test";
var b: string = "another test";
a = b;
b = a; // this gives a compiler error!

编译器的当前版本显示:

Type 'String' is not assignable to type 'string'.
  'string' is a primitive, but 'String' is a wrapper object.
     Prefer using 'string' when possible.

那是一个错误吗?


8
我认为“这是一个bug吗”是一个非常好的哲学问题。它可能是“有意”的,但它会造成困惑和编译错误。我认为至少是一个问题。 - Gherman
1
简单的区别在于 String 和 string 的 typeof 是不同的,因此一个不能分配给另一个。typeof(String) 是 Object,所以我们可以使用 new String('...'),而 typeof(string) 不是 object。 - Badri Paudel
10个回答

453

这里有一个例子,展示了不同之处,将有助于解释。

var s1 = new String("Avoid newing things where possible");
var s2 = "A string, in TypeScript of type 'string'";
var s3: string;

String 是 JavaScript 中的字符串类型,你可以使用它来创建新的字符串,但在 JavaScript 中,很少有人这样做,因为字面量被认为是更好的选择。例如上面的示例中,s2 创建了一个新的字符串而不使用 new 关键字和显式地使用 String 对象。

string 是 TypeScript 中的字符串类型,你可以用它来定义变量、参数和返回值的类型。

额外的注释...

目前(2013 年 2 月),s1s2 都是合法的 JavaScript 语句。s3 是合法的 TypeScript 语句。

使用 String。你可能永远不需要使用它,字符串字面量被普遍认为是初始化字符串的正确方式。在 JavaScript 中,使用对象字面量和数组字面量也被认为更好:

var arr = []; // not var arr = new Array();
var obj = {}; // not var obj = new Object();

如果你真的对字符串很有爱好,你可以用两种方式之一在TypeScript中使用它...

var str: String = new String("Hello world"); // Uses the JavaScript String object
var str: string = String("Hello World"); // Uses the TypeScript string type

谢谢你澄清了这一点。因此,在使用其他处理字符串值的库时,使用原始类型字符串可以避免可能出现的类型转换问题(基于没有人实际使用String的想法)。但是,string和String之间的赋值应该被同等对待吗? - Paul0515
1
实际上,使用它是安全的,因为TypeScript类型被剥离以提供100%兼容的JavaScript(在ES3或ES5版本中,以及版本1 ES6版本中)。我建议使用“string”类型和文字初始化:var s: string = "My String"; - Fenton
就记录而言,由于类型推断的帮助,var s: string = "My String"var s = "My String" 是相同的... 另外,无论我读这个回答多少次,我仍然没有领会 TypeScript 中 string 类型的目的,因为归根结底,('My String')['constructor'] === String... - mindplay.dk
2
如果您没有使用一个值来初始化变量,通常会添加注释。 - Fenton
2
我已经添加了一个答案来澄清"foo"与new String("foo")之间的区别并不是TypeScript引入的新区别 - 我认为将一个称为JS类型,另一个称为TS类型并不有帮助。 - Joe Lee-Moyet
我感觉这里缺少了重要的东西。当你读取JSON数据字符串值时,JSON中的值可以为null。你会使用大写的String变量而不是原始类型来定义你的模型,这样它们也可以为空,对吧? - Placeable

89
两种类型在JavaScript和TypeScript中是不同的——TypeScript只是给我们提供了语法来注释和检查类型。
“String”指的是一种具有“String.prototype”在其原型链中的对象实例。您可以通过各种方式获取这样的实例,例如“new String('foo')”和“Object('foo')”。您可以使用“instanceof”运算符测试“String”类型的实例,例如“myString instanceof String”。
“string”是JavaScript的一种基本类型,“string”值主要是使用文字创建的,例如“'foo'”和“'bar'”,以及各种函数和运算符的结果类型。您可以使用“typeof myString === 'string'”来测试“string”类型。
绝大多数情况下,应该使用string类型——几乎所有接受或返回字符串的API接口都会使用它。当将JS原始类型作为对象使用时,例如访问属性或调用方法,它们都会被包装(boxed)为相应的对象类型。由于String当前在TypeScript核心库中被声明为接口而不是类,因此结构类型意味着string被认为是String的子类型,这就是为什么您的第一行代码可以通过编译类型检查的原因。

48

16

JavaScript中的字符串可以是字符串原始类型或字符串对象。下面的代码显示了它们之间的区别:

var a: string = 'test'; // string literal
var b: String = new String('another test'); // string wrapper object

console.log(typeof a); // string
console.log(typeof b); // object

你的错误:

类型“String”不能赋值给类型“string”。'string'是基元类型,但'String'是包装对象。 尽可能使用“string”。

这是由TS编译器抛出的错误,因为你试图将类型string分配给字符串对象类型(通过new关键字创建)。编译器告诉你应该只使用类型string来描述字符串基元类型,并且你不能使用此类型来描述字符串对象类型。


7

TypeScript: String vs string

类型为 'String' 的参数无法分配给类型为 'string' 的参数。

'string' 是一种原始类型,但 'String' 是一个包装对象。

尽量在可能的情况下使用 'string'。

Demo

字符串对象

// error
class SVGStorageUtils {
  store: object;
  constructor(store: object) {
    this.store = store;
  }
  setData(key: String = ``, data: object) {
    sessionStorage.setItem(key, JSON.stringify(data));
  }
  getData(key: String = ``) {
    const obj = JSON.parse(sessionStorage.getItem(key));
  }
}

字符串基元

// ok
class SVGStorageUtils {
  store: object;
  constructor(store: object) {
    this.store = store;
  }
  setData(key: string = ``, data: object) {
    sessionStorage.setItem(key, JSON.stringify(data));
  }
  getData(key: string = ``) {
    const obj = JSON.parse(sessionStorage.getItem(key));
  }
}

enter image description here


5

简单回答:

  • string => 是一种类型,例如:console.log(typeof 'foo') // string
  • String => 是一个对象,具有一些方法来创建和操作字符串。

3
JavaScript有7种原始类型:字符串(strings)、数字(numbers)、布尔值(booleans)、null、undefined、符号(symbol)和大整数(bigint)。前五种类型从一开始就存在,符号原始类型是在ES2015中添加的,而大整数正在完成中。
原始类型与对象的区别在于它们是不可变的,且没有方法。您可能会反对说字符串确实有方法。
 console.log('primitive'.charAt(3)) // output is "m"

好的,虽然字符串原始值没有方法,但JavaScript也定义了一个String对象类型来提供这些方法。JavaScript可以自由地在原始值和对象类型之间进行转换。当您在字符串原始值上访问像charAt这样的方法时,JavaScript会将其包装在String对象中,调用该方法,然后丢弃该对象。
TypeScript通过为原始值和它们的对象包装器定义不同的类型来模拟这种区别:
- string和String - number和Number - boolean和Boolean - symbol和Symbol - bigint和BigInt
通常情况下,如果您使用String而不是string,则一切都能正常工作,但在某些情况下,编译器会引发错误(如上图所示)。
正如您所看到的,string可以分配给String,但String不能分配给string。
遵循错误消息中的建议,坚持使用字符串。TypeScript随附的所有类型声明都使用它,几乎所有其他库的类型也是如此。

对于更多类似的技巧和建议,我建议阅读 https://effectivetypescript.com/。 - WadeeSami

2

这个错误提示表明你正在尝试将一个字符串类型的值分配给类型为string的变量或参数。在TypeScript中,string是表示字符序列的原始类型,而String是一个包装对象,提供了与字符串相关的其他方法。

错误提示建议你尽可能使用string类型而不是String类型,因为string类型更高效且具有较少的相关开销。这是因为String是一个对象,在JavaScript(因此也在TypeScript)中存储在堆上,并且在创建时需要额外的内存分配。相比之下,string值直接存储在栈上,使得它们更有效地使用。

为了修复这个错误,你需要确保在任何需要的地方都使用string类型,而不是String类型。你可以通过简单地将代码中的String替换为string来实现这一点。例如,如果你有一个类型为String的变量,你可以将其更改为类型为string:

let myString: String = "hello, world!"; // Incorrect
let myString: string = "hello, world!"; // Correct

值得注意的是,通常情况下,您应该尽可能使用string而不是String,因为它更高效且更易于使用。

2
  1. string ==> 原始数据类型。
  2. String ==> 非原始数据类型。它是一个对象,并且可以访问String类的方法和属性。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接