Open aleclarson opened 5 years ago
Treat class Foo {}
differently than class Foo extends Object {}
like so:
extends Object
is omitted from the class
declaration, make Foo extends Object
evaluate to false. Otherwise, behave normally.class Foo {
private _: any
}
class Bar extends Object {
private _: any
}
declare const test: (arg: Object) => void
test(new Foo) // π₯
test(new Bar) // π
declare const test2: (arg: object) => void
test2(new Foo) // π
test2(new Bar) // π
Add a new Exact<T>
type that forbids narrow class types.
T
is a literal type, the resolved type is T
T
is Object
, any object literal is allowed (but Object
sub-classes are not)T
is Array
, any array literal is allowed (but Array
sub-classes are not)T
is Function
, any function literal is allowed (but Function
sub-classes are not)T
is any other class, only instances of T
are allowed (no sub-classes or super-classes)class Foo extends Object {
constructor(public a: number) {}
}
declare const testObject: (arg: Exact<Object>) => void
testObject(new Foo(1)) // π₯
testObject({ a: 1 }) // π
testObject(Object.create(null)) // π
declare const testArray: (arg: Exact<Array>) => void
class MyArray extends Array {}
testArray(new MyArray()) // π₯
testArray([]) // π
declare const testFunc: (arg: Exact<Function>) => void
class MyFunc extends Function {}
testFunc(new MyFunc()) // π₯
testFunc(() => 0) // π
declare const testFoo: (arg: Exact<Foo>) => void
class Cart extends Foo {}
testFoo(new Foo(1)) // π
testFoo(new Cart(2)) // π₯
Related: #12936
@aleclarson - I'm facing the exact same issue in one of my libs. Please let me know if you figure any hacky workarounds. β€οΈ
I have a proxy which should not ever be used for classes. I need a way to say: "This function can take objects, but not ones which are classes"
Trying to solve this problem again, ended up back here.
@DanielRosenwasser @ahejlsberg Can this be brought up in a design meeting soon? π€
I have a proxy which should not ever be used for classes. I need a way to say: "This function can take objects, but not ones which are classes"
I have exactly the same use case.
@AlexGalays , depending on your project you can maybe do what I did:
_noProxy: true
to every class you expect to be usedThis is by no means perfect, but it can put out a few fires at least.
@AlexGalays , depending on your project you can maybe do what I did:
- add a property called
_noProxy: true
to every class you expect to be used- add a condition to your type which takes advantage of this
This is by no means perfect, but it can put out a few fires at least.
Yeah, unfortunately, I don't control all the class combinations, people can use their own :p
Same with my project. They can use any class actually... so I have a long list of things which it should not proxy, and then am hoping to convince users within docs to add _noProxy: true
to anything that messes them up. Once again, not great... but I would have had to give up on the project otherwise.
These examples are more fun.
const $name: { name: string }[] = [
{ name: "test" },
() => { },
function () { },
class Class { },
Boolean,
Object,
];
const $length: { length: number }[] = [
{ length: 1 },
[],
["π₯"],
new Uint16Array(1),
];
Search Terms
Suggestion
Some way to distinguish an object type that only has
Object
in its prototype chain.Use Cases
In this library, we use mapped types to convert immutable objects/arrays into their mutable representation. We never do this for class instances, so I need a way to skip the mapped type when an object type is actually a class type (in order to preserve readonly properties on class instances).
Examples
I have no suggestions for such syntax.
Checklist
My suggestion meets these guidelines:
Related
https://stackoverflow.com/questions/53819550/distinguish-between-plain-objects-and-class-types#53819550