typescript reference own type in return type
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I have a base class ApiModel:
class ApiModel {
static async fetch (params = {}, Model = this, apiPath = this.apiPath): Promise<any | PaginatedResponse> {
let { data } = await axios.get(apiPath, { params })
return Model.transformResponse(data)
}
}
and models that inherit from it:
class User extends ApiModel {
}
Typescript does not like my return definition (any) in combination with the variable type User:
let users: User = await User.fetch() // Assigned expression type any | PaginatedResponse is not assignable to type User
How can I replace any
without explicitly using User
(it needs to be generic, based on extended class)
typescript
add a comment |
I have a base class ApiModel:
class ApiModel {
static async fetch (params = {}, Model = this, apiPath = this.apiPath): Promise<any | PaginatedResponse> {
let { data } = await axios.get(apiPath, { params })
return Model.transformResponse(data)
}
}
and models that inherit from it:
class User extends ApiModel {
}
Typescript does not like my return definition (any) in combination with the variable type User:
let users: User = await User.fetch() // Assigned expression type any | PaginatedResponse is not assignable to type User
How can I replace any
without explicitly using User
(it needs to be generic, based on extended class)
typescript
1
FYI: The error you are getting is not due toany
vsUser
it due to the union withPaginatedResponse
– Titian Cernicova-Dragomir
Jan 4 at 12:12
1
Where isPaginatedResponse
coming from ? Shouldn't it also be generic to allow for model type? I can provide the solution to how to make the static method on the base class work for derived classes, but there are other issues with your code
– Titian Cernicova-Dragomir
Jan 4 at 12:15
add a comment |
I have a base class ApiModel:
class ApiModel {
static async fetch (params = {}, Model = this, apiPath = this.apiPath): Promise<any | PaginatedResponse> {
let { data } = await axios.get(apiPath, { params })
return Model.transformResponse(data)
}
}
and models that inherit from it:
class User extends ApiModel {
}
Typescript does not like my return definition (any) in combination with the variable type User:
let users: User = await User.fetch() // Assigned expression type any | PaginatedResponse is not assignable to type User
How can I replace any
without explicitly using User
(it needs to be generic, based on extended class)
typescript
I have a base class ApiModel:
class ApiModel {
static async fetch (params = {}, Model = this, apiPath = this.apiPath): Promise<any | PaginatedResponse> {
let { data } = await axios.get(apiPath, { params })
return Model.transformResponse(data)
}
}
and models that inherit from it:
class User extends ApiModel {
}
Typescript does not like my return definition (any) in combination with the variable type User:
let users: User = await User.fetch() // Assigned expression type any | PaginatedResponse is not assignable to type User
How can I replace any
without explicitly using User
(it needs to be generic, based on extended class)
typescript
typescript
asked Jan 4 at 12:05
ChrisChris
2,67152361
2,67152361
1
FYI: The error you are getting is not due toany
vsUser
it due to the union withPaginatedResponse
– Titian Cernicova-Dragomir
Jan 4 at 12:12
1
Where isPaginatedResponse
coming from ? Shouldn't it also be generic to allow for model type? I can provide the solution to how to make the static method on the base class work for derived classes, but there are other issues with your code
– Titian Cernicova-Dragomir
Jan 4 at 12:15
add a comment |
1
FYI: The error you are getting is not due toany
vsUser
it due to the union withPaginatedResponse
– Titian Cernicova-Dragomir
Jan 4 at 12:12
1
Where isPaginatedResponse
coming from ? Shouldn't it also be generic to allow for model type? I can provide the solution to how to make the static method on the base class work for derived classes, but there are other issues with your code
– Titian Cernicova-Dragomir
Jan 4 at 12:15
1
1
FYI: The error you are getting is not due to
any
vs User
it due to the union with PaginatedResponse
– Titian Cernicova-Dragomir
Jan 4 at 12:12
FYI: The error you are getting is not due to
any
vs User
it due to the union with PaginatedResponse
– Titian Cernicova-Dragomir
Jan 4 at 12:12
1
1
Where is
PaginatedResponse
coming from ? Shouldn't it also be generic to allow for model type? I can provide the solution to how to make the static method on the base class work for derived classes, but there are other issues with your code– Titian Cernicova-Dragomir
Jan 4 at 12:15
Where is
PaginatedResponse
coming from ? Shouldn't it also be generic to allow for model type? I can provide the solution to how to make the static method on the base class work for derived classes, but there are other issues with your code– Titian Cernicova-Dragomir
Jan 4 at 12:15
add a comment |
1 Answer
1
active
oldest
votes
The error you are getting is not due to any
vs User
it due to the union with PaginatedResponse
.
A union between any
and PaginatedResponse
and will not be assignable to User
. You need to use a type-guard to distinguish between the array result and the PaginatedResponse
So this will work event with any
(since any
is assignable to any other type including User
)
let result = await User.fetch()
if(result instanceof Array) {
const user: User = result;
}else {
const paged = result;
}
That being said, you should still avoid any
(like the plague IMO, if you don't know the type prefer unknown
(see here for unknown vs any))
To get the type of the current class in the static method you can use a generic type parameter in conjunction with the this
parameter annotation.
The exact solution may vary on whether the class is abstract or not and on whether the constructor has parameters or not (and whether derived types have different parameter signatures or not).
The solution below works for non-abstract base class and if derived classes have the same constructor signature (or compatible) as the base class.
interface PaginatedResponse<T> {
start: number;
end: number;
data: T
}
class ApiModel {
static apiPath = ""
static async fetch<T extends typeof ApiModel>(this: T, params = {}, Model = this, apiPath = this.apiPath): Promise<Array<InstanceType<T>> | PaginatedResponse<InstanceType<T>>> {
return null!;
}
}
class User extends ApiModel {
}
(async function (){
let result = await User.fetch()
if(result instanceof Array) {
const user = result; // is User
}else {
const paged = result; // PaginatedResponse<User>
}
})()
Note I filled in PaginatedResponse
with an interface as I was not sure what that type looked like, if the type is under your control I would make it generic to reflect the returned result type.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54038654%2ftypescript-reference-own-type-in-return-type%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The error you are getting is not due to any
vs User
it due to the union with PaginatedResponse
.
A union between any
and PaginatedResponse
and will not be assignable to User
. You need to use a type-guard to distinguish between the array result and the PaginatedResponse
So this will work event with any
(since any
is assignable to any other type including User
)
let result = await User.fetch()
if(result instanceof Array) {
const user: User = result;
}else {
const paged = result;
}
That being said, you should still avoid any
(like the plague IMO, if you don't know the type prefer unknown
(see here for unknown vs any))
To get the type of the current class in the static method you can use a generic type parameter in conjunction with the this
parameter annotation.
The exact solution may vary on whether the class is abstract or not and on whether the constructor has parameters or not (and whether derived types have different parameter signatures or not).
The solution below works for non-abstract base class and if derived classes have the same constructor signature (or compatible) as the base class.
interface PaginatedResponse<T> {
start: number;
end: number;
data: T
}
class ApiModel {
static apiPath = ""
static async fetch<T extends typeof ApiModel>(this: T, params = {}, Model = this, apiPath = this.apiPath): Promise<Array<InstanceType<T>> | PaginatedResponse<InstanceType<T>>> {
return null!;
}
}
class User extends ApiModel {
}
(async function (){
let result = await User.fetch()
if(result instanceof Array) {
const user = result; // is User
}else {
const paged = result; // PaginatedResponse<User>
}
})()
Note I filled in PaginatedResponse
with an interface as I was not sure what that type looked like, if the type is under your control I would make it generic to reflect the returned result type.
add a comment |
The error you are getting is not due to any
vs User
it due to the union with PaginatedResponse
.
A union between any
and PaginatedResponse
and will not be assignable to User
. You need to use a type-guard to distinguish between the array result and the PaginatedResponse
So this will work event with any
(since any
is assignable to any other type including User
)
let result = await User.fetch()
if(result instanceof Array) {
const user: User = result;
}else {
const paged = result;
}
That being said, you should still avoid any
(like the plague IMO, if you don't know the type prefer unknown
(see here for unknown vs any))
To get the type of the current class in the static method you can use a generic type parameter in conjunction with the this
parameter annotation.
The exact solution may vary on whether the class is abstract or not and on whether the constructor has parameters or not (and whether derived types have different parameter signatures or not).
The solution below works for non-abstract base class and if derived classes have the same constructor signature (or compatible) as the base class.
interface PaginatedResponse<T> {
start: number;
end: number;
data: T
}
class ApiModel {
static apiPath = ""
static async fetch<T extends typeof ApiModel>(this: T, params = {}, Model = this, apiPath = this.apiPath): Promise<Array<InstanceType<T>> | PaginatedResponse<InstanceType<T>>> {
return null!;
}
}
class User extends ApiModel {
}
(async function (){
let result = await User.fetch()
if(result instanceof Array) {
const user = result; // is User
}else {
const paged = result; // PaginatedResponse<User>
}
})()
Note I filled in PaginatedResponse
with an interface as I was not sure what that type looked like, if the type is under your control I would make it generic to reflect the returned result type.
add a comment |
The error you are getting is not due to any
vs User
it due to the union with PaginatedResponse
.
A union between any
and PaginatedResponse
and will not be assignable to User
. You need to use a type-guard to distinguish between the array result and the PaginatedResponse
So this will work event with any
(since any
is assignable to any other type including User
)
let result = await User.fetch()
if(result instanceof Array) {
const user: User = result;
}else {
const paged = result;
}
That being said, you should still avoid any
(like the plague IMO, if you don't know the type prefer unknown
(see here for unknown vs any))
To get the type of the current class in the static method you can use a generic type parameter in conjunction with the this
parameter annotation.
The exact solution may vary on whether the class is abstract or not and on whether the constructor has parameters or not (and whether derived types have different parameter signatures or not).
The solution below works for non-abstract base class and if derived classes have the same constructor signature (or compatible) as the base class.
interface PaginatedResponse<T> {
start: number;
end: number;
data: T
}
class ApiModel {
static apiPath = ""
static async fetch<T extends typeof ApiModel>(this: T, params = {}, Model = this, apiPath = this.apiPath): Promise<Array<InstanceType<T>> | PaginatedResponse<InstanceType<T>>> {
return null!;
}
}
class User extends ApiModel {
}
(async function (){
let result = await User.fetch()
if(result instanceof Array) {
const user = result; // is User
}else {
const paged = result; // PaginatedResponse<User>
}
})()
Note I filled in PaginatedResponse
with an interface as I was not sure what that type looked like, if the type is under your control I would make it generic to reflect the returned result type.
The error you are getting is not due to any
vs User
it due to the union with PaginatedResponse
.
A union between any
and PaginatedResponse
and will not be assignable to User
. You need to use a type-guard to distinguish between the array result and the PaginatedResponse
So this will work event with any
(since any
is assignable to any other type including User
)
let result = await User.fetch()
if(result instanceof Array) {
const user: User = result;
}else {
const paged = result;
}
That being said, you should still avoid any
(like the plague IMO, if you don't know the type prefer unknown
(see here for unknown vs any))
To get the type of the current class in the static method you can use a generic type parameter in conjunction with the this
parameter annotation.
The exact solution may vary on whether the class is abstract or not and on whether the constructor has parameters or not (and whether derived types have different parameter signatures or not).
The solution below works for non-abstract base class and if derived classes have the same constructor signature (or compatible) as the base class.
interface PaginatedResponse<T> {
start: number;
end: number;
data: T
}
class ApiModel {
static apiPath = ""
static async fetch<T extends typeof ApiModel>(this: T, params = {}, Model = this, apiPath = this.apiPath): Promise<Array<InstanceType<T>> | PaginatedResponse<InstanceType<T>>> {
return null!;
}
}
class User extends ApiModel {
}
(async function (){
let result = await User.fetch()
if(result instanceof Array) {
const user = result; // is User
}else {
const paged = result; // PaginatedResponse<User>
}
})()
Note I filled in PaginatedResponse
with an interface as I was not sure what that type looked like, if the type is under your control I would make it generic to reflect the returned result type.
answered Jan 4 at 12:52
Titian Cernicova-DragomirTitian Cernicova-Dragomir
74.2k35371
74.2k35371
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54038654%2ftypescript-reference-own-type-in-return-type%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
FYI: The error you are getting is not due to
any
vsUser
it due to the union withPaginatedResponse
– Titian Cernicova-Dragomir
Jan 4 at 12:12
1
Where is
PaginatedResponse
coming from ? Shouldn't it also be generic to allow for model type? I can provide the solution to how to make the static method on the base class work for derived classes, but there are other issues with your code– Titian Cernicova-Dragomir
Jan 4 at 12:15