Jak vytvořit (python-like) NewType v TypeScriptu
V Pythonu (typing) lze vytvořit alias typu (což není nic jiného než nové jméno pro typ) a NewType, což je typ, který je 100% stejný jako základní, ale bude považován za jedinečný systémem typů. Pro rychlé ukázání rozdílu:
UserId = int # Alias, meaning it's not considered a new type
def get_user(uid: UserId):
# so this is the same as "def get_user(uid: int):"
...
get_user(3) # and this is valid
UserId = typing.NewType("UserId", int) # NewType, meaning it is considered a new type
def get_user(uid: UserId):
# so this is NOT the same as "def get_user(uid: int):"
...
get_user(3) # and this throws an error (in type checking)
get_user(UserId(3)) # (this works)
user_id = UserId(3)
get_user(user_id) # as does this
Všimněte si, že i v případě NewType je při běhu programu parametr uid jen celé číslo a lze jej použít přesně tímto způsobem.
V tomto triviálním příkladu nejsou výhody NewType tak zřejmé, ale pokud máte funkci s 5 parametry, některé user_ids, některé user_age, některé department_id atd., je to zachránce života, pokud vám kontrola typů může oznámit, že jste zadali parametry ve špatném pořadí (a ještě lépe, pokud vám IDE jednoduše navrhne přesně tu proměnnou, kterou potřebujete pro každý parametr, protože ví, že máte k dispozici pouze jednu proměnnou typu DepartmentId!)
Jak to udělat stejně v TypeScriptu?
V TypeScriptu můžete snadno vytvářet aliasy typů:
type UserId = number
jak si ale vytvořit něco podobného NewType (kde kompilátor TypeScriptu bude hlásit chybu, pokud přiřadíte obyčejné number funkci, která očekává UserId).
(Všimněte si, že pro vlastní objekty si můžete vytvořit podtřídu; tato otázka je zaměřena převážně na primitivní objekty (řetězec, číslo atd.))
Odpověď č. 1
S trochou hackování v TypeScriptu si můžete vytvořit své vlastní nové typy:
Definujte svůj nový typ jako základní typ plus falešné pole:
type UserId = number & {__my_hidden_type: "userId"}
type DepartmentId = number & {__my_hidden_type: "departmentId"}
// etc...
function getUser(uid: UserId) { }
getUserId(3) // gives error
const notUserId = 3
getUserId(notUserId) // gives error
getUserId(3 as UserId) // works
const userId = 3 as UserId
getUserId(userId) // works
Ve všech ohledech to přesně dělá to, co bych očekával, kromě toho, že IDE si myslí, že na proměnné uid je pole __my_hidden_type; i tak, vzhledem k tomu, že jde o trik, bych byl stále spokojen s čistším řešením.
