-
Notifications
You must be signed in to change notification settings - Fork 12.8k
"Unique symbol" returned from the function becomes "symbol" #24506
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
there are two issues here. first a mutable location (e.g. property assignment) is always widened and does not get the literal type.. e.g.: const s = "str"; // "str"
const x = {
prop: s;
};
x.prop; // string Unless the properties that are declared as readonly (or contextually typed by a readonly property), it will not get the literal type.. For the second issue, for the compiler to verify the relationship, the compiler needs to have access to the unique symbol declaration, otherwise, no grantees can be made that the function is not called multiple times for instance.. e.g. const cls = create().cls;
const prop = create().prop;
|
Is there any workaround to disable this compiler check except for |
you can always cast your way out: const create = () => {
const prop = Symbol();
return {
cls: class A {
public [prop]: string = 'str';
},
prop: prop as typeof prop, // make sure the unique symbol survives the winding
};
}
const result = create();
const prop: ReturnType<typeof create>["prop"] = result.prop; // explicitly type it to the type of the unique symbol.
class B extends result.cls {
public [prop]: string = 'test';
} |
@mhegazy Thanks for the idea. I'm thinking on your words, and there is something that I cannot get intuitively. Actually, I don't quite understand why symbol widens on destructuring. If I replace symbol with string and follow your example, it will work without casting to const create = () => {
const prop = 'value';
return {
cls: class A {
public [prop]: string = 'str';
},
prop: prop as typeof prop,
};
}
const { cls, prop } = create();
class B extends cls {
public [prop]: string = 'test'; // works without explicit cast
} Aren't they the same? String literal saves the type for some reason without widening, but symbol loses it. |
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed. |
@mhegazy Is the following behavior intended? function test<T>(fn: () => T): T {
return fn()
}
declare const foo: unique symbol
// Type 'symbol' is not assignable to type 'unique symbol'
let result: typeof foo = test(() => foo) |
@aleclarson |
This may be related, but when I return a unique symbol in an async function, TypeScript infers its return type as const VALUE = Symbol('VALUE')
async function foo() { return VALUE }
const result = foo() // Promise<symbol> This can be problematic when I accept as argument a callback that may return a unique symbol or a promise: function useCallback(callback: () => typeof VALUE | Promise<typeof VALUE>) {
// ...
}
// OK
useCallback(() => VALUE)
// Type 'Promise<symbol>' is not assignable to type 'unique symbol | Promise<unique symbol>'.
// Type 'Promise<symbol>' is not assignable to type 'Promise<unique symbol>'.
// Type 'symbol' is not assignable to type 'unique symbol'.
useCallback(async () => VALUE) |
I'm struggling with the same issue. In case someone else is wondering how to get around this: Doing |
TypeScript Version: 3.0.0-dev.20180530
Search Terms:
unique symbol, property, dynamic class creation
Code
Expected behavior:
No error.
Actual behavior:
When
unique symbol
is returned from function, it becamessymbol
that forbids working with class properties defined inside the function as well as class itself.Playground Link:
Link
Related Issues:
Didn't find any
The text was updated successfully, but these errors were encountered: