#
私有字段的使用來替代不太嚴格的 private
等。TypeScript 3.8爲僅類型導入和導出添加了新語法。html
import type { SomeThing } from "./some-module.js";
export type { SomeThing };
複製代碼
playground
上試一試,這樣導入和導出,ts 是不會解析,這個特性不經常使用,若是你子配置以下問題的時候可能遇到isolatedModulesTypeScript
的transpileModuleAPI
或Babel
下遇到問題,則此功能多是相關的。使用這樣的導入的新類型也是不支持擴展等方法的react
import type { Component } from "react";
interface ButtonProps {
// ...
}
class Button extends Component<ButtonProps> {
// ~~~~~~~~~
// error! 'Component' only refers to a type, but is being used as a value here.
// ...
}
複製代碼
typescript
中咱們能夠這麼使用私有字段
了class Person {
#name: string
constructor(name: string) {
this.#name = name;
}
greet() {
console.log(`Hello, my name is ${this.#name}!`);
}
}
let jeremy = new Person("Jeremy Bearimy");
jeremy.#name
// ~~~~~
// Property '#name' is not accessible outside class 'Person'
// because it has a private identifier.
複製代碼
!!! 和常規屬性(這裏特別比較 private
修飾符聲明的比較)不一樣,私有字段(private fields)擁有下面這些特性。git
#
字符開頭。有時咱們稱這些 prviate name
。TypeScript
輔助功能修飾符,例如 public
,private
不能在私有字段上使用。除了能保存本身的私有這一屬性之外,私有字段的另外一個好處是咱們剛纔提到的惟一性。例如,常規屬性聲明易於在子類中被覆蓋。而 private fields
是受保護的。github
class C {
foo = 10;
cHelper() {
return this.foo;
}
}
class D extends C {
foo = 20;
dHelper() {
return this.foo;
}
}
let instance = new D();
// 'this.foo' refers to the same property on each instance.
console.log(instance.cHelper()); // prints '20'
console.log(instance.dHelper()); // prints '20'
複製代碼
訪問任何其餘類型的私有字段都將致使 TypeError!!
typescript
class Square {
#sideLength: number;
constructor(sideLength: number) {
this.#sideLength = sideLength;
}
equals(other: any) {
return this.#sideLength === other.#sideLength;
}
}
const a = new Square(100);
const b = { sideLength: 100 };
// Boom!
// TypeError: attempted to get private field on non-instance
// This fails because 'b' is not an instance of 'Square'.
console.log(a.equals(b));
複製代碼
#
定製的私有字段仍是使用 private
修飾符啦?當涉及到屬性時,TypeScript
的private
修飾符會並無徹底正確的執行,它的行爲徹底像普通屬性同樣,而且沒有辦法告訴它是使用private
修飾符並無徹底的生效。咱們稱之爲 soft privacy
, 咱們依然能夠經過 ['foo']
這樣的形式訪問到。看下面的代碼:api
class C {
private foo = 10;
}
// This is an error at compile time,
// but when TypeScript outputs .js files,
// it'll run fine and print '10'.
console.log(new C().foo); // prints '10'
// ~~~
// error! Property 'foo' is private and only accessible within class 'C'.
// TypeScript allows this at compile-time
// as a "work-around" to avoid the error.
console.log(new C()["foo"]); // prints '10'
複製代碼
好處固然是幫助您在使用一些 api 的時候解決兼容的問題,可是這種方法不太嚴格。async
#
私有字段,是徹底訪問不到的class C {
#foo = 10;
}
console.log(new C().#foo); // SyntaxError
// ~~~~
// TypeScript reports an error *and*
// this won't work at runtime!
console.log(new C()["#foo"]); // prints undefined
// ~~~~~~~~~~~~~~~
// TypeScript reports an error under 'noImplicitAny',
// and this prints 'undefined'.
複製代碼
結論就是,若是你想嚴格的保護您的私有屬性的值,就使用 `#` 便可,子類繼承的時候也無需擔憂命名衝突的問題。當咱們仍是使用 `private` 的時候就須要注意對私有修飾符的定義的值修改的問題了。 ide
typescript 也支持這種用法啦,在導入模塊的 as 從新定義模塊名的模塊的時候,咱們能夠從新導出到單獨模塊名。函數
// menu.tsfetch
export const MENU1 = __('nav: 菜單 1');
export const MENU2 = __('nav: 菜單 2');
export const MENU3 = __('nav: 菜單 3');
export const MENU4 = __('nav: 菜單 4');
export const DEMO = __('nav:Demo');
複製代碼
// module.ts
import * as menu from "./menu.ts";
console.log(menu.MENU1) // 'nav: 菜單 1';
console.log(menu.MENU2) // 'nav: 菜單 2';
// ....
export { menu };
複製代碼
ps: ECMAScript 2020 最近也添加了這種語法!
import * as React from 'react'; vs import React from 'react';
這兩個使用有什麼區別嗎?
import * as React from 'react';
...or like this:
import React from 'react';
複製代碼
The first imports everything in the react module (see: Import an entire module's contents)
The second imports only the default module export (see: Importing defaults)
簡而言之就是咱們使用的 import React from 'react'
實際上是導出的默認的模塊,而用到 * as
是導出所有模塊。
JavaScript
常會引入一個async
函數來使用 await
.JavaScript
中(以及其餘大多數具備相似功能的語言)await
僅在 async
函數體內被容許。可是,對於 top await
,咱們能夠 await
在模塊的頂層使用。async function main() {
const response = await fetch("...");
const greeting = await response.text();
console.log(greeting);
}
main()
.catch(e => console.error(e))
複製代碼
const response = await fetch("...");
const greeting = await response.text();
console.log(greeting);
// Make sure we're a module
export {};
複製代碼
請注意,這裏有一個微妙之處:頂層await僅在模塊的頂層起做用,而且只有當TypeScript找到一個真正可用的模塊才容許使用,咱們能夠用一個
export {}
來檢測是否在模塊下使用。
這個方法還在實驗中不建議使用,等 3.9 吧